【转】第一篇-linux中socket通信

发布时间 2023-10-16 09:56:56作者: 立志做一个好的程序员

 

转, 原文:https://zhuanlan.zhihu.com/p/628583834

----------------

 

客户端和服务端是如何通信的

在linux中客户端和服务端通信的流程如图所示:

流程分析:
服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

TCP服务端通过依次调用 socket(),bind(),listen()之后,就会监听指定的socket地址了。客户端如果调用connect()发出一个 连接请求,服务端监听到这个 连接请求之后,就会调用accept()函数去接受请求,这样连接就建立好了,之后就可以进行网络IO操作了。

连接是如何建立的

前面我们讲的,客户端调用connect()发起连接请求,服务端监听到这个连接请求,就会调用accept()接受请求,这个流程是两者建立连接的流程,这个连接建立的流程就是三次握手协议。

  1. 当客户端调用connect()时,触发了连接请求,向服务器发送了syn包,这时客户端会进入阻塞状态;
  2. 服务端监听到连接请求,即收到了syn包,调用accept函数接受请求向客户端发送syn&ack,这时服务端也会进入阻塞状态;
  3. 客户端收到收到服务器的syn&ack包,connect()会返回给服务端ack;
  4. 服务端收到ack之后,accept()方法会返回(即执行结束)

思考:客户端和服务端具体socket是如何进行通信的?(我也不知道这样描述对不对)
假设服务端已经创建一个socket,用于监听客户端的连接请求。现在有两个客户端socket A和B尝试连接到服务端。

  1. 客户端socket A向服务端发送连接请求
  2. 服务端使用accept函数接受客户端socket A的连接请求,并为其创建一个新的socket socketA,该新的socket将用于与客户端socket A进行通信。
  3. 客户端socket B也向服务端发送连接请求
  4. 服务端使用accept函数同样接受客户端socket B的连接请求,并为其创建一个新的socket socketB,该新的socket将用于与客户端socket B进行通信。

此时,服务端就有了两个新的socket:socketA用于与客户端socket A进行通信,socketB用于与客户端socket B进行通信。这两个socket是独立的,互不干扰。每个socket都可以单独处理某个客户端的请求和数据传输。这样,服务端就可以同时处理多个客户端的请求和数据传输,提高了并发性能和效率。
需要注意的是,服务端通过这些socket与不同的客户端进行通信,服务端原始的socket只用于监听客户端的连接请求,而不用于实际的数据传输,因此它可以同时处理多个客户端的连接请求。而新创建的每个socket则对应一个独立的客户端,并且每个socket只能用于与对应的客户端进行通信。
ps:这里再啰嗦一句,服务端原始socket只用于建立连接,数据传输由新的socket去做。

思考:我们前面学习了客户端和服务端如何进行通信,但是我们发现一个问题,就是那种通信方式只适用于一个客户端和一个服务端进行通行,如果我们想多个客户端和一个服务端通信,要怎么做呢?这里就引出了网络IO通信模型


参考文章:

Linux的SOCKET编程详解_linux socket_hguisu的博客-CSDN博客