一、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连接的请求,断开过程需要经过“四次握手”(过程就不细写了,就是服务器和客户端交互,最终确定断开)

网络上已经有编写好的开源类库GCDAsyncSocket 和GCDAsyncUdpSocket  这是GCD版的  比AsyncSocket 和AsyncUdpSocket估计要好用点 用法也很简单,跟http很类似  只要指定服务器的ip和端口 然后再实现各种回调就行,原生态实现正在摸索。。。。。socket默认情况下就是采用TCP协议,创建之后通信双方的socket会一直保持连接,除非手动close或因为网络原因close,所以,此种状况对服务器而言是有一定资源消耗的,这种模式只适应与对服务器小规模的访问,特别是对于实时性很高的应用,如视频直播、呼叫系统等,而http一般都是短连接的,一次请求完之后客户端便会于服务端端开连接
   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的更多相关文章

  1. 32.网络编程TCP/UDP服务

    网络编程TCP: 服务器端口了解: port:0~65535 web服务:80 邮箱服务:556 0~1024:为服务默认的公认端口,一般我们不能用 套接字:socket socket作用 ip:po ...

  2. java 网络编程-tcp/udp

    --转自:http://blog.csdn.net/nyzhl/article/details/1705039 直接把代码写在这里,解释看这里吧:http://blog.csdn.net/nyzhl/ ...

  3. 28_网络编程-TCP/UDP

    一.传输层       1.定义       IP首部有一个协议字段,用来标识网络层(IP)的上一层所采用的是哪一种传输层协议.根据这个字段的协议号,就可以识别IP传输的数据部分究竟是TCP的内容还是 ...

  4. Java网络编程——TCP/UDP

    UDP:面向无连接 ☆ 将数据及源地址和目的地址封装成数据包中 ☆ 每个数据报的大小限制在64K ☆ 不可靠协议 ☆ 不需要建立连接,速度快 TCP:面向有连接 ☆ 建立连接,形成传输数据的通道 ☆ ...

  5. python 网络编程-TCP/UDP

    摘抄自:廖雪峰的官方网站:http://www.liaoxuefeng.com/ TCP客户端和服务器端代码: #coding=utf-8 #客户端程序TCP 连接 import socket s=s ...

  6. 网络编程——TCP协议、UDP协议、socket套接字、粘包问题以及解决方法

    网络编程--TCP协议.UDP协议.socket套接字.粘包问题以及解决方法 TCP协议(流式协议) ​ 当应用程序想通过TCP协议实现远程通信时,彼此之间必须先建立双向通信通道,基于该双向通道实现数 ...

  7. iOS网络编程笔记——Socket编程

    一.什么是Socket通信: Socket是网络上的两个程序,通过一个双向的通信连接,实现数据的交换.这个双向连路的一端称为socket.socket通常用来实现客户方和服务方的连接.socket是T ...

  8. IOS网络编程:HTTP

    IOS网络编程:HTTP HTTP定义了一种在服务器和客户端之间传递数据的途径. URL定义了一种唯一标示资源在网络中位置的途径. REQUESTS 和 RESPONSES: 客户端先建立一个TCP连 ...

  9. Socket网络编程(TCP/IP/端口/类)和实例

    Socket网络编程(TCP/IP/端口/类)和实例 原文:C# Socket网络编程精华篇 转自:微冷的雨 我们在讲解Socket编程前,先看几个和Socket编程紧密相关的概念: TCP/IP层次 ...

随机推荐

  1. 关于Themleaf学习总结

    此篇记录学习Themleaf测试的相关用例: study01 Thymeleaf 的HelloWorld级别的例子 简单介绍Thymeleaf的工作流程 study02 使用spring.thymel ...

  2. 理解Python命名机制

    理解Python命名机制 本文最初发表于恋花蝶的博客(http://blog.csdn.net/lanphaday),欢迎转载,但必须保留此声明且不得用于商业目的.谢谢. 引子 我热情地邀请大家猜测下 ...

  3. Configuring HDFS High Availability

    Configuring HDFS High Availability 原文请訪问 http://blog.csdn.net/ashic/article/details/47024617,突袭新闻小灵儿 ...

  4. Informatica 常用组件Lookup缓存之三 重建查找高速缓存

    如果您认为查找源在 PowerCenter 上次构建高速缓存时已更改,则可指示 PowerCenter 重建查找高速缓存. 重建高速缓存时,PowerCenter 会覆盖现有永久高速缓存文件而创建新的 ...

  5. Informatica 常用组件Source Qualifier之九 创建SQ转换

    可以配置 Designer 在您将源拖到映射中时默认创建源限定符转换,您也可以手动创建源限定符转换. 默认创建源限定符转换 可以配置 Designer 在您将源拖到映射中时自动创建一个源限定符转换. ...

  6. uva 10160 Servicing Stations(DFS+剪枝)

    Servicing stations A company offers personal computers for sale in N towns (3 <= N <= 35). The ...

  7. after the first ten days

    This is the first week for me to speak English formally. There’re two main problems: First, I’m scar ...

  8. Qt学习之对话框与主窗口的创建

    Qt中的信号与槽机制 qt中槽和普通的C++成员函数几乎是一样的--可以是虚函数,可以被重载,可以是共有的,保护的或者私有的. 槽可以和信号连接在一起,在这种情况下,每当发射这个信号的信号,就会自动调 ...

  9. 请教如何改善C#中socket通信机客户端程序的健壮性

    我是做Socket的新手,最近做了一个Socket客户端程序,连接Server的时候,如果server存在,并且允许连接的话,程序无错,正常执行:但是如果Server不存在,或者拒绝连接,程序就会卡住 ...

  10. OpenGL使用libPng读取png图片

    #include<stdarg.h> #include<png.h> #include<glut.h> #include<math.h> #includ ...