Socket实现简单的聊天功能,我们先来看下效果:
通过这张图,我们更容易的去理解这些API,客户端和服务端的不同点就是建立连接部分。服务端需要bind listen accept ,多个客户端可以连接一个服务端。
1> domain:协议域,又称协议族(family)。常用的协议族有AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域Socket)、AF_ROUTE等。协议族决定了socket的地址类型。
2> type:指定Socket类型。常用的socket类型有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等。流式Socket(SOCK_STREAM)是一种面向连接的Socket,针对于面向连接的TCP服务应用。数据报式Socket(SOCK_DGRAM)是一种无连接的Socket,对应于无连接的UDP服务应用。
3> protocol:指定协议。常用协议有IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。
注意:1.type和protocol不可以随意组合,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当第三个参数为0时,会自动选择第二个参数类型对应的默认协议。
返回值: 如果调用成功就返回新创建的套接字的描述符,如果失败就返回INVALID_SOCKET(Linux下失败返回-1) */
socket(AF_INET, SOCK_STREAM, 0);
1> 套接字描述符
2> 指向数据结构sockaddr的指针,其中包括目的端口和IP地址
3> 参数二sockaddr的长度,可以通过sizeof(struct sockaddr)获得
返回值:成功则返回0,失败返回非0,错误码GetLastError()
connect(self.mSocketId,(conststructsockaddr*)&socket_add,sizeof(socket_add));
1> 套接字描述符
2> 指向数据结构sockaddr的指针,其中包括目的端口和IP地址
3> sockaddr的长度,可以通过sizeof(struct sockaddr)获得
返回值: 成功则返回0,失败返回非0,错误码GetLastError()。
bind(mSocketId, (const struct sockaddr *)&socket_add, sizeof(socket_add));
1> 套接字描述符
2> 最大支持连接数
返回值:如果失败则返回 -1
listen(mSocketId, MaxConnectCount);
1> 客户端socket
2> 指向数据结构sockaddr的指针
返回值:失败则返回 -1 SOCKET_ERROR,成功返回客户端编号
accept(mSocketId, (structsockaddr*)&client_addr, &addr_length);
1> 一个用于标识已连接套接口的描述字。
2> 包含待发送数据的缓冲区。
3> 缓冲区中数据的长度。
4> 调用执行方式。
返回值:如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR
一个中文对应 3 个字节!UTF8 编码!
send(mSocketId, send_msg, strlen(send_msg), 0);
1> 客户端socket
2> 接收内容缓冲区地址
3> 接收内容缓存区长度
4> 接收方式,0表示阻塞,必须等待服务器返回数据
返回值:如果成功,则返回读入的字节数,失败则返回 -1 SOCKET_ERROR
recv(mSocketId, buffer,sizeof(buffer),0);
TCP三次握手
连接上Socket后,发消息时,用Wireshark网络封包分析工具,抓到以下数据。我们来看一下TCP的三次握手。
TCP是因特网中的传输层协议,使用三次握手协议建立连接。
当主动方发出SYN连接请求后,等待对方回答TCP的三次握手SYN+ACK ,并最终对对方的 SYN 执行 ACK 确认。
这种建立连接的方法可以防止产生错误的连接,TCP使用的流量控制协议是可变大小的滑动窗口协议。
IP层协议属于不可靠的协议,IP层并不关心数据是否发送到了对端,TCP通过确认机制来保证数据传输的可靠性
TCP三次握手的过程如下:
(1)客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。
(2)服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。
(3)客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。
TCP Window Update 滑动窗口,在一个文件传输的时候, 数据接收方需要阻止它的TCP Window降为0, 意味着window填满了. 如果一个TCP Window变为0了, 或者接近0了, 这就会警告数据发送方没有更多空间来接受更多数据了.文件传输会停止, 直到收到一个update说明buffer已经清空了.
Frame:Frame是帧,数据单元,对应物理层。
LoopBack:对应数据链路层,以太网卡等,这里用的本地回环地址LoopBack。
IPV4:对应网络层,IP协议(协议栈可以想象成漏斗型,IP在中间作为上下层的连接点),Src:源地址 Dst:目标地址,IP层协议层无端口
TCP:进入TCP层,有端口,对应传输层。
滑动窗口
用上面蓝色线代表服务端,下面代表客户端。中间箭头代表发起和响应的网络请求。绿色框代表滑动窗口。
滑动窗口是控制接收以及同步数据范围的,通知发送端目前接收的数据范围,用于流量控制,接收端使用。
拥塞窗口是控制发送速率的,避免发的过多,发送端使用。
两个窗口的维护是独立的,滑动窗口主要由接收方反馈缓存情况来维护,拥塞窗口主要由发送方的拥塞控制算法检测出的网络拥塞程度来决定的。
TCP四次挥手
断开连接时,用Wireshark网络封包分析工具,抓到了TCP的四次挥手
(1) 关闭时首先调用close,称该端执行“主动关闭”(active close)。该端的TCP于是发送一个FIN分节,表示数据发送完毕。
(2) 接收到这个FIN的对端执行 “被动关闭”(passive close),这个FIN由TCP确认。
注意:FIN的接收也作为一个文件结束符(end-of-file)传递给接收端应用进程,放在已排队等候该应用进程接收的任何其他数据之后,因为,FIN的接收意味着接收端应用进程在相应连接上再无额外数据可接收。
(3) 一段时间后,接收到这个文件结束符的应用进程将调用close关闭它的套接字。这导致它的TCP也发送一个FIN。
(4) 接收这个最终FIN的原发送端TCP(即执行主动关闭的那一端)确认这个FIN。
TCP 和 UDP
TCP:(传输控制协议)
TCP的优点: 稳定 TCP的可靠体现在TCP在传递数据之前,通过三次握手建立连接,形成传输数据的通道,四次挥手完成断开,是可靠协议,安全送达。
在连接中进行大数据传输(数据大小不受限制)TCP保证数据顺序,UDP不保证。
缺点:必须建立连接,效率会稍低。
应用场景: 下载数据
UDP(用户数据协议)
速度快,UDP没有TCP的握手,UDP是一个无状态的传输协议,不需要建立连接,所以它在传递数据时非常快。
只管发送,不确认对方是否接收到,将数据及源和目的封装成数据包中,每个数据报的大小限制在64k之间。
缺点:不需要建立连接,因此是不可靠协议,会丢包。
应用场景:流媒体数据传输,直播时界面会模糊,马赛克的感觉(数据丢帧) QQ语音 QQ视频 王者荣耀等也是UDP
OSI网络模型(太官方不太懂,举个例子一下就明白了)
物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是1、0转化为电流的强弱来进行传输,到达目的地后再转化为1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。
例:数据在电线传输过程中,用电流的高低频代表 01 二进制数据,但是电信号容易收到影响(数据传输中需要打包,有种格式叫 :标准帧格式。物理层(电线)
数据链路层:定义了如何格式化数据以进行传输,以及如何让控制对物理介质的访问。这一层通常还提供错误检测和纠正,以确保数据的可靠传输。
例: 数据链路层(数据打包的过程)
网络层:在位于不同地理位置的网络中的两个主力系统之间提供连接和路径选择。Internet的发展使得从世界各站点访问信息的用户数量大大增加,而网络层正是管理这种连接的层。
例:网络层( 选择数据传输路径,路由器)
传输层:定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据)。主要是将从下层接受的数据进行分段传输,到达目的地址后再进行重组。通常把这一层数据叫做段。
例:(有两个协议TCP/UDP,保证数据正确送达)
会话层:通过传输层(端口号:传输端口与接受端口)建立数据传输的通路。主要在你的系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)。
例:(怎么接收你发来的数据,需要建立网络会话,对二进制数据解析,可以认为两个交流的协议,设定一个协议例如HTTP)
表示层:可确保一个系统的应用层所发送的信息可以被另外一个系统的应用层读取。
例:表示层(解析完数据需要表示,是文字还是图片视频)
应用层:最靠近用户的OSI层。这一层为用户的应用程序(例如电子邮件、文件传输和终端仿真)提供网络服务
例:应用层(表示完展示在UI界面上)
HTTP
在HTTP/1.1协议中,定义了8种发送http请求的方法
GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT、PATCH
HTTP超文本传输协议,是短连接,是客户端主动发送请求,服务器做出响应,服务器响应之后,链接断开。
HTTP是一个属于应用层面向对象的协议,HTTP有两类报文:请求报文和响应报文。
HTTP请求报文:一个HTTP请求报文由请求行、请求头部、空行和请求数据4部分组成。
HTTP响应报文:由三部分组成:状态行、消息报头、响应正文。
HTTPS:安全超文本传输协议(Secure Hypertext Transfer Protocol),它是一个安全通信通道,基于HTTP开发,用于客户计算机和服务器之间交换信息,使用安全套结字层(SSI)进行信息交换,即HTTP的安全版。
Scoket连接和HTTP连接的区别
HTTP协议是基于TCP连接的,是应用层协议,主要解决如何包装数据。Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。
HTTP连接:短连接,客户端向服务器发送一次请求,服务器响应后连接断开,节省资源。服务器不能主动给客户端响应(除非采用HTTP长连接技术),iPhone主要使用类NSURLConnection。
Socket连接:长连接,客户端跟服务器端直接使用Socket进行连接,没有规定连接后断开,因此客户端和服务器段保持连接通道,双方可以主动发送数据,一般多用于游戏.Socket默认连接超时时间是30秒,默认大小是8K(理解为一个数据包大小)。
HTTP:一般用于非实时连接的请求,只有客户端主动向服务器发送请求时,服务器才能返回数据给客户端。
XMPP:基于xml通讯的协议,基于TCP发送xml数据,一般用于即时通信。
GET和POST的区别:
GET请求:参数在地址后拼接,没有请求数据,不安全(因为所有参数都拼接在地址后面),不适合传输大量数据(长度有限制,为1024个字节)。
GET提交、请求的数据会附在URL之后,即把数据放置在HTTP协议头中。
以?分割URL和传输数据,多个参数用&连接。如果数据是英文字母或数字,原样发送,
如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密。
POST请求:参数在请求数据区放着,相对GET请求更安全,并且数据大小没有限制。把提交的数据放置在HTTP包的包体中.
GET提交的数据会在地址栏显示出来,而POST提交,地址栏不会改变。
传输数据的大小:
GET提交时,传输数据就会受到URL长度限制(1KB),POST由于不是通过URL传值,理论上不受限。
安全性:
POST的安全性要比GET的安全性高;
通过GET提交数据,用户名和密码将明文出现在URL上,比如登陆界面有可能被浏览器缓存
参考资料:https://objccn.io/issue-10-6/
SocketDemo:https://github.com/TeeMoYan/TMSocketDemo.git