socket到底是什么?
network socket即网络套接字,后面简写成socket,是操作系统提供的网络通信接口,让我们能够使用TCP/IP栈传输数据。可以简单的理解为socket是在tcp/ip协议栈的一种编程接口。
socket是一切网络通信的基础,无论是web服务器nginx,还是数据库mysql,进行网络通信都是使用socket。
我讲个真实的事情,笔者毕业的时候去华为面试,边上的一个研究生姐姐面挂后痛哭自责,从她的同学和她沟通中我得知原来是面试官让她现场写一个socket通信的代码段,结果她不会。其实当时我也写不出来。
socket通信的流程
任何基于TCP的网络应用都遵循这个流程。
服务端
- 使用socket()系统调用创建socket,socket会返回一个文件描述符,发送和接收数据也就是读写这个文件。因为文件描述符就是一个整形,因此一个socket占用4字节的空间
- 将socket与一个ip端口对绑定
- 调用listen激活socket,进入监听状态。listen的第二参数backlog用来指定等待队列的最大长度,队列中是已经完成三次握手的连接,当这个队列满了之后,新的请求会被丢弃。
The backlog argument defines the maximum length to which the queue of pending connections for sockfd may grow. ... The behavior of the backlog argument on TCP sockets changed with Linux 2.2. Now it specifies the queue length for completely established sockets waiting to be accepted, instead of the number of incomplete connection requests.
- 调用accept接收新的连接,这个系统调用会一直阻塞直到有新的连接请求,即TCP的SYNC报文。成功建立连接后返回一个新的socket。这个socket负责与客户端进行通信,因此一个tcp连接需要两个socket文件描述符。
- 接收/发送数据,调用close关闭连接,与读/写/关闭文件的操作一致
客户端
- 使用socket()系统调用创建socket
- 调用connect连接到一个服务端的地址,地址信息包含了服务端socket绑定的ip端口对。服务端socket accept后成功返回。客户端的端口有操作系统自动分配。
- 接收/发送数据,调用close关闭连接,与读/写/关闭文件的操作一致
socket示例
下面是一个使用socket编写TCP服务端与客户端的典型示例,客户端代码在前,服务端代码在后,整个通信流程如下图所示:
这个示例很简单,每一步都有详细的注释。服务端监听端口,建立连接后客户端发送一个字符串,服务端接收到后回送给客户端,之后两边都关闭socket从而完成4次握手断开连接。