客户端进程与服务器进程的socket通信可以简单地描述如下图:
1、连接建立阶段
当套接字创建后,它的端口号和IP地址都是空的,因此应用程序要调用bind来指明套接字的本地地址(本地端口号和本地IP地址)。
在服务器调用bind时,就是把本地端口号和本地IP地址填写在已经创建的套接字中。
客户端可以不调用bind,这时由操作系统内核自动分配一个动态端口号,通信结束后由系统收回。
服务端的情况:
服务器在调用bind后,还必须调用listen把套接字设置为被动方式,以便随时接受客户的服务请求。UDP服务器由于只提供无连接服务,不使用listen系统调用。
服务器紧接着就调用accept,以便把远端客户进程发来的连接请求提取出来。
当服务器主进程调用accept后,将会发生以下步骤:
·主进程为每一个新的连接请求新建一个套接字(连接套接字),以及创建一个从属进程;
·从属进程用新建的连接套接字与客户进程建立连接,然后在这个连接上传送和接受数据;
·主进程利用原来的套接字重新调用accept,继续接受下一个连接请求。
这样服务器就能同时处理多个连接,并发工作。
任意时刻服务器中总是存在一个主服务器进程和零个或多个从属服务器进程。主服务器进程用原来的套接字接收连接请求,从服务器进程用新创建的套接字和相应的客户端建立连接,传输数据。
客户端的情况:
当客户端调用socket创建套接字之后,客户进程就调用connect,以便和远端服务器建立连接(这是主动打开,相当于客户端发起连接请求)。在connect系统调用中,客户必须指明远端的IP地址和端口号。
2、数据传输阶段
客户端和服务器都使用send系统调用传送数据,使用recv系统调用接收数据。通常,客户端使用send发送请求,而服务器使用send发送回答。服务器使用recv接收客户端用send调用发送的请求。客户端在发完请求后用recv接收回答。
调用send需要三个参数:数据要发往的套接字描述符、要发送的数据的地址以及数据的长度。
调用recv需要三个参数:要使用的套接字描述符、缓存地址以及缓存空间的长度。
3、连接释放阶段
一旦客户或服务器结束使用套接字,就把套接字撤销。调用close释放连接和撤销套接字。
来源参考:
谢希仁,《计算机网络第五版》,电子工业出版社,p279