TCP套接字编程—具体流程梳理

一个上午都在调试一个服务器端监听程序,测试的客户端怎么都连不上,然后疯狂在网上搜寻答案无果,最后无意中发现竟是系统没有联网。唉,顿时就像是在debug过程中发现某处少了一个逗号是一个样的郁闷!不过这个纠结的过程却让我把TCP套接字编程的整个过程又有了重新的认识。


TCP是一种可靠的面向连接的通信协议,因此在通信之前需要确认通信的双方,称之为客户端和服务器端。一般由客户端向服务器端发送连接请求,然后服务器端确认请求,最后客户端再确认连接,即为三次握手。在TCP套接字网络编程中,存在更多的细节,大致的流程如下图所示:




通俗地说,由TCP数据报首部结构我们知道,唯一标识一个TCP连接的结构是一个插口对,也就是客户端ip、客户端端口、服务器端ip、服务器端端口四元组。这个四元组结构就是一个套接字。在客户端中,我们知道自己的ip、端口(用户定义或者内核分配),也知道目的服务器的插口地址,而在服务器端的套接字只有服务器本身的插口地址,在有客户端来连接的时候配成一个新的已连接的套接字。


服务器端:

1、创建一个套接字:调用socket()函数,将返回一个套接字描述符sockfd;

2、为创建的套接字绑定本地插口地址:因为由socket()函数创建的套接字所包含的信息很少,只有一些协议族和类型等

   ,并没有指定任何的地址,因此需要创建一个套接字地址结构对象,初始化后绑定到创建的套接字上,即下一步的操       作。

3、将套接字绑定到本地插口地址上:创建一个本地套接字地址结构对象(sockaddr_in),然后通过bind()函数将这个对      象和前面的套接字绑定。

4、好了,服务器端的套接字有本地插口地址了,这个套接字是用来监听的,也就是说这个套接字是用来监听是否有指向      该服务器端的连接请求,由listen()函数将这个套接字变成监听套接字

5、监听套接字还是不完整的,它是一个没有源端插口地址的套接字,因此当有客户端连接到该服务器端的时候,就会与      监听套接字“组合”成一个完整的已连接套接字了(当然不是真的组合,可以这么来理解这个过程)。服务器端是通      过accept()函数来创建一个已连接套接字。

注意区分监听套接字和已连接套接字:监听套接字是在服务器的生命期过程中一直存在的。而已连接套接字是由内核为每个与服务器连接的客户端创建的。后者在完成给定客户端服务时候被关闭。


基本过程就是这样,下面是一个最简单的获取客户端ip地址和端口号的服务器端程序:




在这里,accept()函数来读取已完成连接队列中客户端请求,如果队列为空,则使得服务器端进程陷入休眠状态,直到有客户端请求完成连接被唤醒。此时没有客户端连接请求时,运行结果如下:




即陷入休眠状态。


客户端:

1、创建一个套接字:调用socket()函数,返回一个套接字描述符sockfd;

2、这里有个需要注意的地方,就是客户端的套接字需不需要bind一个本地插口地址。(前一篇博文中有说)一般没有        这个需要。但是我们需要一个目的服务器端的插口地址,但是不是用来绑定到套接字上面,而是用来connect到服务      器端。

3、调用connect()函数后,客户端出发三次握手。发出请求到完成三次握手过程中,客户端的连接请求将进入服务器端      的未完成连接队列,完成三次握手后将进入已完成连接队列中,后者将会唤醒服务器端的进程,从而继续执行              accept()函数。

然后就可以互相通信传递数据了。


代码如下:



运行之后将唤醒服务器端程序,服务器端程序唤醒后的运行结果如下:



发布了68 篇原创文章 · 获赞 42 · 访问量 22万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章