Socket,TCP,UDP,HTTP基本通信原理和OC版本Demo
来源:互联网 发布:张卫健眼睛知乎 编辑:程序博客网 时间:2024/04/28 06:01
非常通俗的例子->寄快递
- TCP和UDP是传输方式—> 例如空运,轮渡,陆运
- HTTP,XMPP则是数据传输格式协议 –> 寄送的东西(吃的,用的,玩的。。。)
- socket理解为传输层和应用层之前的抽象对象,通过对TCP/IP传世方式的封装,调用其封装好的方法就可实现通信,但是必须知道双方的IP,端口和协议–>就好比知道双方的寄件地址
什么是Socket?
TCP、UDP,HTTP 底层通信都是通过 socket 套接字实现
网络上不同的计算机,也可以通信,那么就得使用网络套接字(socket)。
socket就是在不同计算机之间进行通信的一个抽象。
他工作于TCP/IP协议中应用层和传输层之间的一个抽象
总结如下:
1.Socket 是对 TCP/IP 协议族的一种封装,是应用层与TCP/IP协议族通信的中间软件抽象层。从设计模式的角度看来,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
2.Socket 还可以认为是一种网络间不同计算机上的进程通信的一种方法,利用三元组(ip地址(主机),协议(传输方式),端口(主机上的进程标志))就可以唯一标识网络中的进程,网络中的进程通信可以利用这个标志与其它进程进行交互。
3.socket保证了不同计算机之间的通信,也就是网络通信。对于网站,通信模型是客户端服务器之间的通信。
两个端都建立一个socket对象,然后通过socket对象对数据进行传输。通常服务器处于一个无线循环,等待客户端连接
通俗的理解:
Socket的英文原义是“孔”或“插座”,Socket通常也称作”套接字”,用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原意那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110伏交流电,有的则提供有线电视节目。 客户软件将插头插到不同编号的插座,就可以得到不同的服务
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket
应用程序通常通过”套接字”向网络发出请求或者应答网络请求
演示Demo
什么是TCP
TCP(传输控制协议,HTTP的交互方式就是TCP交互方式,需要建立连接,一种面向连接的、可靠的字节流服务)
在一个TCP连接中,仅有两方进行彼此通信。广播和多播不能用于TCP
- 建立连接,形成数据传输通道
- 在链接中进行大数据传输,数据不受限制
- 通过三次握手完成链接,是可靠协议,安全送达协议
- 必须建立连接,效率很稍微低
所谓三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送3个包。
三次握手的目的是连接服务器指定端口,建立 TCP 连接,并同步连接双方的序列号和确认号,交换 TCP 窗口大小信息。在 socket 编程中,客户端执行 connect() 时。将触发三次握手。
* 第一次握手(SYN=1, seq=x): 客户端发送一个 TCP 的 SYN 标志位置1的包,指明客户端打算连接的服务器的端口,以及初始序号 X,保存在包头的序列号(Sequence Number)字段里。 发送完毕后,客户端进入 `SYN_SEND` 状态。* 第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1): 服务器发回确认包(ACK)应答。即 SYN 标志位和 ACK 标志位均为1。服务器端选择自己 ISN 序列号,放到 Seq 域里,同时将确认序号(Acknowledgement Number)设置为客户的 ISN 加1,即X+1。 发送完毕后,服务器端进入 `SYN_RCVD` 状态。* 第三次握手(ACK=1,ACKnum=y+1) 客户端再次发送确认包(ACK),SYN 标志位为0,ACK 标志位为1,并且把服务器发来 ACK 的序号字段+1,放在确定字段中发送给对方,并且在数据段放写ISN的+1 发送完毕后,客户端进入 `ESTABLISHED` 状态,当服务器端接收到这个包时,也进入 `ESTABLISHED` 状态,TCP 握手结束。
什么是UDP
UDP (用户数据报协议,无连接,不可靠的网络协议,用于多播,广播,例如上课同步直播)
- 将数据以及源(我的电脑IP)和目的(别人电脑的IP)封装成数据包中,不需要建立连接
- 每个数据报的大小限制在64k之内,为什么小一点呢,例如你20分钟的大小发一次,那出错了,你这20分支都看不到了,
如果你一秒钟发一次,你错过了,下一秒就能继续接上,所以大小有限制 - 无需连接,因此是不可靠协议
- 不需要建立连接,速度快
1. UDP协议的服务器端流程
UDP协议的服务器端程序设计的流程分为套接字建立、套接字与地址结构进行绑定、收发数据、关闭套接字等过程,分别对应于函数socket()、bind()、sendto()、recvfrom()和close()。
建立套接字过程使用socket()函数,这个过程与TCP协议中的含义相同,不过建立的套接字类型为数据报套接字。地址结构与套接字文件描述符进行绑定的过程中,与TCP协议中的绑定过程不同的是地址结构的类型。当绑定操作成功后,可以调用recvfrom()函数从建立的套接字接收数据或者调用sendto()函数向建立的套接字发送网络数据。当相关的处理过程结束后,需要调用close()函数关闭套接字。
2. UDP协议的客户端流程
UDP协议的服务器端程序设计的流程分为套接字建立、收发数据、关闭套接字等过程,分别对应于函数socket()、sendto()、recvfrom()和close()。
建立套接字过程使用socket()函数,这个过程与TCP协议中的含义相同,不过建立的套接字类型为数据报套接字。建立套接字之后,可以调用函数sendto()向建立的套接字发送数据或者调用recvfrom()函数从建立的套接字收网络数据。当相关的处理过程结束后,需要调用close()函数关闭套接字。
3. UDP协议服务器和客户端之间的交互
UDP协议中服务器和客户端的交互存在于数据的收发过程中。进行网络数据收发的时候,服务器和客户端的数据是对应的:客户端发送数据的动作,对服务器来说是接收数据的动作;客户端接收数据的动作,对服务器来说是发送数据的动作。
UDP协议服务器与客户端之间的交互,与TCP协议的交互相比较,缺少了二者之间的连接。这是由于UDP协议的特点决定的,因为UDP协议不需要流量控制、不保证数据的可靠性收发,所以不需要服务器和客户端之间建立连接的过程。
什么是HTTP
- HTTP底层就是通过Socket建立链接通信管道,实现数据传输
- HTTP是一个TCP传输协议的其中一个方式,他是可靠的,安全的协议,和XMPP类似,一种定义好的数据格式传输协议
- HTTP构建于TCP/IP协议之上,默认端口号是80
- HTTP是无连接无状态的
HTTP超详细分解传送门
写个简单的TCP服务端和客户端交互的原理
1.使用-> CocoaAsyncSocket (7.5.1),用一个类封装方法,开启runloop循环
int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... NSLog(@"Hello, World!"); MKJSocketService *socketService = [[MKJSocketService alloc] init]; [socketService connected]; [[NSRunLoop mainRunLoop] run]; } return 0;}
2.由于是服务端,我们需要一个服务端的socket以及一个可变数组存放连接的客户端socket
@interface MKJSocketService () <GCDAsyncSocketDelegate>@property (nonatomic,strong) GCDAsyncSocket *serviceSocket; // 服务端socket@property (nonatomic,strong) NSMutableArray *connectionClientSockets; // 已经链接的socket@end@implementation MKJSocketService- (NSMutableArray *)connectionClientSockets{ if (_connectionClientSockets == nil) { _connectionClientSockets = [[NSMutableArray alloc] init]; } return _connectionClientSockets;}- (instancetype)init{ if (self = [super init]) { /** 注意:这里的服务端socket,只负责socket(),bind(),lisence(),accept(),他的任务到底结束,只负责监听是否有客户端socket来连接 */ self.serviceSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)]; } return self;}
注意:这里的服务端socket只是完成到监听部分就结束了,后续的所有操作,read或者write或者其他都是客户端Socket的调用
3.调用连接的方法,监听可以连接 的客户端
- (void)connected{ NSError *error = nil; // 给一个需要连接的端口,0-1024是系统的 [self.serviceSocket acceptOnPort:3666 error:&error]; if (error) { NSLog(@"3666服务器开启失败。。。。。"); } else { NSLog(@"开启成功,并开始监听"); }}// 有客户端连接该服务器进行会话 Mac 终端下调用telnet IP port进行与服务器的链接,如果链接上了就会调用这个方法- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket{ NSLog(@"服务器%@",sock); NSLog(@"客户端%@ IP:%@,%d 连接成功",newSocket,newSocket.connectedHost,newSocket.connectedPort); // 1.如果不用全局变量存取,直接就会推出 [self.connectionClientSockets addObject:newSocket]; // 2.连接完成之后进行 客户端的sock进行监听状态 [newSocket readDataWithTimeout:-1 tag:0]; // 3.write目的就是发送数据 有人连接到服务端之后就进行一系列响应 NSMutableString *options = [NSMutableString string]; [options appendString:@"欢迎来到东莞 请输入下面的数字选择服务\n"]; [options appendString:@"[0]按摩\n"]; [options appendString:@"[1]洗脚\n"]; [options appendString:@"[2]大保健\n"]; [options appendString:@"[3]special services\n"]; [options appendString:@"[4]退出\n"]; // 服务端发送数据 [newSocket writeData:[options dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];}
注意:[newSocket readDataWithTimeout:-1 tag:0];
调用者不是服务端的socket,服务端的socket只负责到监听部分,之后就不需要了,这里的调用方是连接的客户端,而且每次接受数据或者发送数据之后都要调用,才能进行下一次的收发数据
4.接收到客户端的消息以及客户端请求断开如何操作
/** 这个是服务端的代码,这里的write就是服务器发送数据,而且这里的发送socket对象也是连接的客户端socket 当有连接好的客户端之后发送消息给服务器,就能通过该方法受到消息,在通过消息,服务端在进行write数据给客户端展示 */- (void)socket:(GCDAsyncSocket *)clientSock didReadData:(NSData *)data withTag:(long)tag{ NSString *receiveStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; switch ([receiveStr integerValue]) { case 0: [self writeDataWithSocket:clientSock message:@"按摩188,这边请\n"]; break; case 1: [self writeDataWithSocket:clientSock message:@"洗脚288,这边请\n"]; break; case 2: [self writeDataWithSocket:clientSock message:@"大保健啊小伙子,来来来\n"]; break; case 3: [self writeDataWithSocket:clientSock message:@"哎呦喂,可以啊,小伙子要来哪一套\n"]; break; case 4: [self exitSocket:clientSock]; break; default: [self writeDataWithSocket:clientSock message:@"没有您要的服务\n"]; break; } [clientSock readDataWithTimeout:-1 tag:0];}/** 断开链接调用 */- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{ NSLog(@"失去连接了");}/** 发送数据给客户端 */- (void)writeDataWithSocket:(GCDAsyncSocket *)socket message:(NSString *)msg{ [socket writeData:[msg dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];}/** 断开连接,会调用Connection closed by foreign host. 并且发送数据到客户端 最终从服务端的数组中移除,释放内存,断开socket @param socket 需要断开的客户端socket */- (void)exitSocket:(GCDAsyncSocket *)socket{ [self writeDataWithSocket:socket message:@"离开东莞\n"]; [self.connectionClientSockets removeObject:socket]; NSLog(@"currentSocket:%ld",self.connectionClientSockets.count);}
5.一个建议的聊天客服功能就结束了,打开Demo,然后运行起来,再打开终端输入
telnet IP地址 端口号 确认之后就是链接成功了,就可以一些简单的交互了
Demo传送门
- Socket,TCP,UDP,HTTP基本通信原理和OC版本Demo
- TCP,UDP,Socket和HTTP
- Socket、HTTP和TCP、UDP
- TCP,UDP,Socket和HTTP
- Socket通信原理,TCP,UDP协议
- <>socket通信-udp和TCP-串口通信
- C# socket通信TCP和UDP方式
- 基于tcp和udp的socket通信
- C# socket udp和tcp通信学习
- Socket之TCP和UDP协议通信
- Socket、HTTP和TCP、UDP简介
- Socket、HTTP和TCP、UDP简介
- HTTP、TCP、UDP、Socket
- TCP、UDP、SOCKET、HTTP
- HTTP、TCP、UDP、Socket
- HTTP、TCP、UDP、Socket
- tcp、udp、http、socket
- TCP、UDP、HTTP、SOCKET
- 155. Min Stack
- Convolutional Neural Network For Sentence Classification<Yoon Kim>解析(一)
- IPC(一)--IPC简介和IPC产生的问题
- Struts2中过滤器和拦截器的区别
- 查找成绩并折算后输出
- Socket,TCP,UDP,HTTP基本通信原理和OC版本Demo
- 492. Construct the Rectangle [LeetCode]
- 【C++】定义常量
- spring jpa 级联的属性操作
- 1080 线段树练习 codevs
- 蓝桥-算法-枚举
- ImportError: No module named tornado.ioloop 记录过程
- Android音视频学习第8章:使用fmod对音频进行变调处理
- 12.1.3