iOS 网络编程 TCP/UDP HTTP
一、HTTP协议的主要特点:
1. CS模式 
2. 简单快速:只需要传送请求方法和路径。(常用方法有GET,HEAD,POST) 
3. 灵活:任意对象都可以,类型由Content-Type加以标记 
4. 无连接、无状态 即每次连接只处理一个请求,对于事务处理没有记忆能力 
http表示要通过HTTP协议来定位网络资源;host表示合法的Internet主机域名或者IP地址;port制定一个端口号,为空时使用缺省端口号80;abs_path指定请求资源的URI;如果URL中没有给出abs_path,那么当它作为请求URI时,必须以“/”的形式给出(此过程由浏览器完成)。
二、TCP/UDP区别和联系 
1.TCP是面向连接的可靠的传输控制协议,UDP是面向非连接的用户数据报协议. 
2.TCP(三次握手保证相对可靠性)可传大量数据,速度相对比较慢,UDP一次性传输少量对可靠性要求不高的数据,速度比较快 
tcp一般用于音频、视频等数据的传输,资源能耗比较小,对可靠性要求不高,即使丢失一两条数据也不会产生太大影响。
三、Socket连接和Http连接的区别 
1.http是基于socket之上的,socket是一套完成tcp和udp协议的接口 
2.HTTP协议:简单对象访问协议,对应于应用层 ,HTTP协议是基于TCP连接的 
3.tcp协议: 对应于传输层 
4.ip协议: 对应于网络层  
TCP/IP是传输层协议,主要解决数据如何在网络中传输;而HTTP是应用层协议,主要解决如何包装数据。 
Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。 
http是短连接,客户端向服务端发送一次请求,服务端响应后连接即断掉;socket是长连接,一般情况下,如果服务器端或者客户端主机down了,网络故障,或者两者长时间没有数据传输,连接可能会断。所以当以个socket连接中没有数据的传输,为了维持连接需要发送心跳消息。
四、三次握手的过程不再赘述,主要来了解下socket建立网络连接的步骤 
建立socket连接至少需要一堆套接字,其中一个运行于客户端,另一个运行于服务端(ClientSocket、ServerSocket) 
套接字建立连接的过程分为三步:服务器监听、客户端请求、连接确认 
1。服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。 
2。客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。 
3。连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
五、HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
AsyncSocket是IOS下专门用于socket套接字开发的开源库,它封装了CFNetwork/BSD Socket.提供了异步的开发模型和简便的开发接口。它支持TCP/UDP,支持UDP组播
AsyncSocket支持GCD/Runloop模式 支持ARC 使用时需要增加两个库 CFNetwork.frame和Security.frame
六、UDP编程 
server端流程: 
1. socket创建套接字 
2. bind绑定port 
3. recv接收、send发送数据 
4. close关闭socket套接字 
client端流程 
1.socket创建套接字 
2.bind绑定port端口(可选) 
3. recv接收 send发送数据 
4. close关闭socket套机制
UDP编程涉及到 ip和字符串的转化如下
/*绑定ip地址 */
inet_pton(AF_INET,"192.168.101.2",&addr.sin_addr);
/*把地址sin_addr转化成字符串ipBuf*/
inet_ntop(AF_INET,&srcaddr.sin_addr,ipBuf,16);UDP基本API 
1. 创建UDP的套接字int sd = socket(AF_INET,SOCK_DGRAM,0); 
2. 设置端口可以重用 int nOptval = 1;   
ret = setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,(const void*)&nOptval,sizeof(int));
3. 绑定端口 ret = bind(sd,(struct sockaddr *)&addr,addrlen); 
4. 给某个地址发送数据ssize_t sendLen = sendto(sd,res,strlen(res),0,(struct sockaddr *)&srcaddr,sizeof(srcaddr)); 
5. 接收来自sd的数据ssize_t recvLen = recvfrom(sd,&info,sizeof(info),0,(struct sockaddr *)&srcaddr,&addrlen); 
6. 关闭套接字 Close(sd);
UDP 编程示例 
server端 : 新建工程 Cococa Application 引入AsyncSocket 
引入头文件 #import “AsyncUdpSocket.h” 以及代理 AsyncUdpSocketDelegate
  _udpSocketServer = [[AsyncUdpSocket alloc] initWithDelegate:self];
    //绑定端口 用于标识socket对象
    if(![_udpSocketServer bindToPort:5678 error:nil]){
        NSLog(@"绑定失败");
    }
    //监听状态 是否有客户端发送来的消息
    [_udpSocketServer receiveWithTimeout:-1 tag:100];
代理回调
#pragma maek- socketDelegate
//收到消息时的回调
-(BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port{
    NSLog(@"port:%d",port);
    NSString* messege = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"recieve:%@",messege);
    [sock receiveWithTimeout:-1 tag:200];
    return YES;
}上述代码即可实现简单的UDPServer端
UDPClient 代码(简单示例) 
同样的要声明UDP对象 然后发送消息
NSString* messege = @"UDPClient 消息";
    NSData* data = [messege dataUsingEncoding:NSUTF8StringEncoding];
    /*
     *发送消息
     host: 制定服务器的ip地址
     port: 服务器的端口
     -1 不限时发送
     tag 对此次操作的标记
     */
    [_clientSocket sendData:data toHost:@"127.0.0.1" port:5678 withTimeout:-1 tag:0];
/*发送成功的回调方法是*/
- (void)onUdpSocket:(AsyncUdpSocket *)sock didSendDataWithTag:(long)tag{
    NSLog(@"发送成功!");
}
TCP编程 
server端流程 
1. socket创建socket套接字 
2. bind绑定port端口 
3. listen监听端口 
4. close关闭socket套机制 
client端流程 
1.socket创建套接字 
2.bind绑定port端口(可选) 
3.connect服务器端口 
4.close关闭socket套机制
了解下 tcp的重传策略: TCP用于控制数据段是否需要重传的依据是设立重发定时器。在发送一个数据段的同时启动一个重发定时器,AC(Ackonowlegement)就关闭该定时器,如果在定时器超时前没有收到确认,则重传该数据段。在选择重发时间的过程中,TCP必须具有自适应性。它需要根据互联网当时的通信情况,给出合适的数据重发。
TCP编程实例 
server  
1.引入头文件 #import “AsyncSocket.h” AsyncSocketDelegate
   _tcpServer = [[AsyncSocket alloc]initWithDelegate:self];
    //服务端对应的ip地址和端口,_serverSocket负责监听是否有客户端接入
    //[_tcpServer acceptOnInterface:@"127.0.0.1" port:5678 error:nil];
    //服务端负责监听是否有客户端接入此端口,host可以缺省不写
    [_tcpServer acceptOnPort:5678 error:nil];2.发现有客户端接入时响应
-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket{
    NSLog(@"new socket host:%@ port:%d",newSocket.connectedHost,newSocket.connectedPort);
    //将新生成的socket对象加入数组中
    [_array addObject:newSocket];
    //负责不限时的监听客户端是否发送消息过来
    [newSocket readDataWithTimeout:-1 tag:1];
}3 收到客户端发送过来的消息时
-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    NSString *message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"receive:%@",message);
    //告诉sock,继续监听客户端
    [sock readDataWithTimeout:-1 tag:2];
 }
4连接的客户端长时间不活跃时触发下面的方法
- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err{
    NSLog(@"willDisconnect!");
}5 断开连接时
//已经断开连接
- (void)onSocketDidDisconnect:(AsyncSocket *)sock{
    NSLog(@"%s",__FUNCTION__);//__FUNCTION__ 能够打印出当前函数的名称,一般用于对程序进行暴力调试时
}client编程 
1. 初始化一个AsyncSocket对象 
_clientSocket = [[AsyncSocket alloc] initWithDelegate:self]; 
2. 与指定的服务器进行连接
if (!_clientSocket) {
        //创建一个客户端对象,并设置delegate
        _clientSocket = [[AsyncSocket alloc] initWithDelegate:self];
    }
    //先判断是否与指定服务器连接
    if ([_clientSocket isConnected]) {
        //断开连接
        [_clientSocket disconnect];
    }
    //与指定服务器连接
    //connectToHost 服务端的ip地址
    //port 服务端的端口:端口的值可随意约定
    [_clientSocket connectToHost:@"127.0.0.1" onPort:5678 error:nil];
3.发送消息
 NSString *message = @"hello server!";
    //将数据转换成data
    NSData *data = [message dataUsingEncoding:NSUTF8StringEncoding];
    //将data发给服务器
    //data 发送的数据, timeout:-1  不限时发送, tag,对此次交互的标记
    [_clientSocket writeData:data withTimeout:-1 tag:0];
4.回调方法
//当客户端与服务端连接成功时,调用此方法
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{
    NSLog(@"与服务器:%@ %d 相连接",host,port);
}
//消息发送成功后,调用此方法
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag{
    NSLog(@"send!");
}
点解此处下载 demo 
今天主要是tcp和udp的编程 明天更新 http和流媒体
iOS中的TCP,UDP,socket的学习
先贴一下之前学习过的代码:
加入CFNetwork.framework,去github上下载AsyncSocket
TCP
- (void)viewDidLoad
{
[super viewDidLoad]; recvArray = [[NSMutableArray alloc] init];
//服务端
recvSocket = [[AsyncSocket alloc] initWithDelegate:self];
//客户端
sendSocket = [[AsyncSocket alloc] initWithDelegate:self]; //服务端开始等待别的客户端的链接
//65535 >5000
[recvSocket acceptOnPort:5678 error:nil];
//那么什么时候接受到了链接
} //调用这个方法就证明接受到了一个链接
- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket{
[recvArray addObject:newSocket];
//等待客户端发送数据
[newSocket readDataWithTimeout:-1 tag:100];
//什么时候读取到了数据
} //调用这个方法就证明接受到了客户端发送的数据
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
NSString* str = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
contentView.text = [NSString stringWithFormat:@"%@\n对方说:%@",contentView.text,str];
//继续等待服务端发送数据
[sock readDataWithTimeout:-1 tag:100];
} //============= //调用这个方法的时候,就证明链接成功
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{ } - (void)sendText:(id)sender{
//如果没链接,那么去链接服务端
if (sendSocket.isConnected == NO) {
[sendSocket connectToHost:ipField.text onPort:5678 withTimeout:60 error:nil];
//什么时候知道链接成功
} NSData* data = [sendField.text dataUsingEncoding:NSUTF8StringEncoding];
//发送数据
[sendSocket writeData:data withTimeout:60 tag:100];
//什么时候知道数据发送成功
} //调用这个方法,就证明数据发送成功
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag{ }
UDP
- (void)viewDidLoad
{
[super viewDidLoad]; recvSocket = [[AsyncUdpSocket alloc] initWithDelegate:self];
//绑定端口
[recvSocket bindToPort:5888 error:nil]; sendSocket = [[AsyncUdpSocket alloc] initWithDelegate:self];
[sendSocket bindToPort:5999 error:nil]; //等待接受数据
[recvSocket receiveWithTimeout:-1 tag:100];
//什么时候接受到了数据 }
//调用这个方法的时候证明接收到了数据
- (BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port{ NSString* str = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
contentView.text = [NSString stringWithFormat:@"%@\n%@:%@",contentView.text,host,str];
[recvSocket receiveWithTimeout:-1 tag:100]; return YES;
} - (void)sendText:(id)sender{
NSData* data = [sendField.text dataUsingEncoding:NSUTF8StringEncoding];
//发送数据
[sendSocket sendData:data toHost:ipField.text port:5888 withTimeout:60 tag:100];
//什么时候发送成功
} //这里就发送成功了
- (void)onUdpSocket:(AsyncUdpSocket *)sock didSendDataWithTag:(long)tag{ }
首先说一下他们直接的联系,UDP和TCP就像声明的一个协议,是需要传送的东西也就是内容,而scoket就像是一个通道,用于传送这些内容,也就是用socket来实现。
UDP:UDP是一种面向无连接的用户数据报服务(user data protocol),不需要和服务器也能交互,只需要知道ip和监听端口,不需要链接没有目的的socket,只是将数据报投递出去,不管接收方是否成功接收到,因此是一种不可靠的传输,可能会造成数据丢包,但由于这些特征,传输效率要优于TCP。
TCP:TCP是一种面向连接的传输控制协议(transform contorl protocol),必须要和服务器交互,具有高安全性,可靠性,需要和服务器进行三次握手,能根据具体网络拥堵情况进行延时。
Socket:Socket有两种连接操作方式,面向连接的和面向无连接的。使用UDP就是面向无连接的,使用TCP就是面向连接的。使用UDP无需要指定一个socket目的地,而是用TCP必须要指定一个socket目的地,需要进行预链接,否则连接不到。
socket就像是API,二UDP/TCP就是协议,使用scoket来实现内容的传送。
TCP的3次握手:
建立起一个TCP连接需要经过“三次握手”:
第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”(过程就不细写了,就是服务器和客户端交互,最终确定断开)
http是凌驾于socket之上的高级协议,而socket是比较底层的通讯方式,只是建立了一个连接通道,具体上面传输什么样的数据,按照什么格式传输,需要你自己定义,所以这就需要重新编写定义服务端与客户端的所应遵循的规定,而http已经被前人们定义使用过了
先去github的网站下载最新的包,然后先看看介绍。写的比较详细了
https://github.com/robbiehanson/CocoaAsyncSocket/wiki/Intro_GCDAsyncSocket
网上很多都是老版本的帖子。官方已经推出了GCDAsyncSocket来代替以前老的AsyncSocket。
我的项目是no-ARC的,这个框架只有arc的版本。所以引入GCDAsyncSocket的.h和.m文件后,修改xcode中项目的属性。
1)targets中“build settings”中找到Compiler for c/c++/Objective-c的选项。改为Apple LLVM compiler 3.0 只要是3.0或以上就可以;
2)在“build phases”中“compile sources”中找到GCDAsyncSocket.m,增加参数-fobj-arc;
3)引入GCDAsyncSocket所需要的框架,CFNetwork和security这两个。
知识补充:
使用Socket进行C/S结构编程,连接过程

服 务器端监听某个端口是否有连接请求。服务器端程序处于堵塞状态,直到客户端向服务器端发出连接请求,服务器端接受请求程序才能向下运行。一旦连接建立起 来,通过Socket可以获得输入输出流对象。借助于输入输出流对象就可以实现与客户端的通讯,最后不要忘记关闭Socket和释放一些资源(包括:关闭 输入输出流)。
客户端流程是先指定要通讯的服务器IP地址、端口和采用的传输协议(TCP或UDP),向服务器发出连接请求,服务器有应答请求之后,就会建立连接。之后与服务器端是一样的了。
在iOS中,客户端Socket编程可以使用的技术有三种:
1 使用NSStream。面向Objective-C语言的实现,由苹果提供的Foundation框架提供的API;
2 使用CFStream。面向C语言的实现,由苹果提供的Core Foundation框架提供的API;
BSD Socket。 也叫伯克利套接字(Berkeley Socket),是Unix平台下广泛使用的Socket编程。它是面向C语言实现 的,完全使用C编写,使用起来比较麻烦。它是伯克利加州大学(University of California, Berkeley)的学生开发的。
在iOS中,服务器端Socket编程可以使用技术有二种:
1 使用CFStream。面向C语言的实现,由苹果提供的Core Foundation框架提供的API;
2 BSD Socket。 也叫伯克利套接字(Berkeley Socket),是Unix平台下广泛使用的Socket编程。它是面向C语言实 现的,完全使用C编写的,使用起来比较麻烦。它是伯克利加州大学(University of California, Berkeley)的学生开发的。
iOS 网络编程 TCP/UDP HTTP的更多相关文章
- 32.网络编程TCP/UDP服务
		网络编程TCP: 服务器端口了解: port:0~65535 web服务:80 邮箱服务:556 0~1024:为服务默认的公认端口,一般我们不能用 套接字:socket socket作用 ip:po ... 
- java 网络编程-tcp/udp
		--转自:http://blog.csdn.net/nyzhl/article/details/1705039 直接把代码写在这里,解释看这里吧:http://blog.csdn.net/nyzhl/ ... 
- 28_网络编程-TCP/UDP
		一.传输层 1.定义 IP首部有一个协议字段,用来标识网络层(IP)的上一层所采用的是哪一种传输层协议.根据这个字段的协议号,就可以识别IP传输的数据部分究竟是TCP的内容还是 ... 
- Java网络编程——TCP/UDP
		UDP:面向无连接 ☆ 将数据及源地址和目的地址封装成数据包中 ☆ 每个数据报的大小限制在64K ☆ 不可靠协议 ☆ 不需要建立连接,速度快 TCP:面向有连接 ☆ 建立连接,形成传输数据的通道 ☆ ... 
- python  网络编程-TCP/UDP
		摘抄自:廖雪峰的官方网站:http://www.liaoxuefeng.com/ TCP客户端和服务器端代码: #coding=utf-8 #客户端程序TCP 连接 import socket s=s ... 
- 网络编程——TCP协议、UDP协议、socket套接字、粘包问题以及解决方法
		网络编程--TCP协议.UDP协议.socket套接字.粘包问题以及解决方法 TCP协议(流式协议)  当应用程序想通过TCP协议实现远程通信时,彼此之间必须先建立双向通信通道,基于该双向通道实现数 ... 
- iOS网络编程笔记——Socket编程
		一.什么是Socket通信: Socket是网络上的两个程序,通过一个双向的通信连接,实现数据的交换.这个双向连路的一端称为socket.socket通常用来实现客户方和服务方的连接.socket是T ... 
- IOS网络编程:HTTP
		IOS网络编程:HTTP HTTP定义了一种在服务器和客户端之间传递数据的途径. URL定义了一种唯一标示资源在网络中位置的途径. REQUESTS 和 RESPONSES: 客户端先建立一个TCP连 ... 
- Socket网络编程(TCP/IP/端口/类)和实例
		Socket网络编程(TCP/IP/端口/类)和实例 原文:C# Socket网络编程精华篇 转自:微冷的雨 我们在讲解Socket编程前,先看几个和Socket编程紧密相关的概念: TCP/IP层次 ... 
随机推荐
- C语言:指针的几种形式
			字符串的两种形式: 1.字符数组 char name[32] = “zhangsan”;//只能在初始化时这样做 strcpy(name,”lisi”);//整体赋值只能通过s ... 
- hdu 4107 Gangster(线段树,时间卡得很严)
			这道题目的数据卡得好厉害. 题目明显是考察线段树延迟标记的,但是因为要考虑到p的值,这种延迟是有条件的:在该节点下所有的数据对于p都应该位于p的同一侧.要么都比p大,要么都比p小. 开始的时候我用一个 ... 
- Android中intent如何传递自定义数据类型
			转载自:http://www.cnblogs.com/GoAhead/archive/2012/07/16/2593868.html 大家好,好久不见,今天要给大家讲一下Android中Intent中 ... 
- 机器视觉之 ICP算法和RANSAC算法
			临时研究了下机器视觉两个基本算法的算法原理 ,可能有理解错误的地方,希望发现了告诉我一下 主要是了解思想,就不写具体的计算公式之类的了 (一) ICP算法(Iterative Closest Poin ... 
- mobile移动网页开发常用代码模板
			index.html <!DOCTYPE HTML> <html> <head> <!--申明当前页面的编码集--> <meta http-equ ... 
- [Backbone]5. Model & View, toggle between Models and Views -- 2
			Dr. Goodparts is pretty flaky and has been cancelling a lot of appointments lately. He's asked for a ... 
- IOS遇到的问题总结
			1.NSString *path = [[NSBundle mainBundle] pathForResource:@"desc" ofType @"plist" ... 
- 修复损坏的 shapefile
			一.SHP文件 Shapefile文件(简称SHP)作为ESRI一种经典的数据格式,被很多其他软件所支持,如CAD.MapGIS等,虽然也有一些限制(如无法进行拓扑分析.字段长度为10个字符等),但其 ... 
- 修改上一篇文章的node.js代码,支持调用自定义页面
			上一篇文章所有请求只能调用index.html,现在做个改造,允许调用自定义页面 服务端 app.js var app = require('http').createServer(handler) ... 
- oracle 之监听保护
			今天是2013-08-24,不对刚刚过了12点,应该是2013-08-25日,今天我的同事对数据库 进行监听安全加固失败,然后 我的哥们也做了同样的实验,结果还是失败,至此我不知道 什么原因,在此想对 ... 
