socket的tcp连接中的监听套接字和已连接套接字

今天在看eXosip代码的时候发现一个问题,在eXosip中使用TCP的socket实现了一个pipe管道,具体的原理是,打开一个TCP的socket然后设置成监听socket,再打开另一个socket作为pipe的一端向监听socket发起连接,监听socket经过accept后返回一个已连接socket,该socket作为pipe的另一端,这个很像用sockpair创建的socket对。但是我发现,在连接完成以后监听socket并没有关闭,带着这个疑惑我上网查了一些资料。

20111123055456302

以下是我的理解(没有看过TCP的源代码,只是猜测)。TCP协议作为一个可靠的协议是有状态的,协议栈在每个连接上都维护了一个有限状态机来处理连接,上面是一个TCP的fsm的状态转移图,TCP会根据从IP层获取的包的TCP包头来匹配状态机实例(根据客户端的协议地址,即ip地址和端口号),然后将TCP包交给相应的状态机处理,如果没有匹配的状态机应该另作处理(比如发送reset)。在应用层创建一个listen的socket时应该会在相应的协议地址(bind的地址)上创建一个处于listen状态的状态机实例,这时如果有客户端发起连接请求(connect)时,当前状态机应该会产生一个新的状态机实例,并且处于SYN收到状态,之前的状态机会继续处于listen状态,新产生的状态机应该对应已连接队列中的一个半连接,当accept后会进入established状态,同时会产生一个新的套接字对应该状态机,即accept返回的套接字。此时如果关闭监听套接字,那么该套接字对应的状态机实例进入close状态后销毁,如果再有客户端发起connect请求时,由于没有处于listen状态的fsm实例来匹配该TCP包,因此会返回reset,但是之前创建的处于established状态的状态机实例还在,通信还能继续。根据以上的分析,在pipe完成连接后,关闭监听socket也不会影响pipe通信,但是在进程中打开fd的数目是有限制的,在不需要接受新的connect请求的情况下应该关闭监听socket以节省系统资源。

posted @ 2012-10-04 21:04  wulax  阅读(2738)  评论(0编辑  收藏  举报