全部博文(240)
分类: LINUX
2011-11-08 22:48:29
作者:孙晓明,讲师。
这周同学们在做网络编程的时候,碰到一个监听套接字的问题,在这里大概描述一下:
比如我的程序开了一个监听端口,与客户端建立连接之后,生成了一个新套接字。这时我执行了只关闭监听端口的语句,结果却发现监听端口和已建立的连接仍然存在。我都已经关闭了监听套接字,为什么客户端还可以继续往监听端口发信息?这到底是因为什么呢?新套接字和监听套接字有什么关系呢?
比如,你开了80监听端口,有一个客户连接你accept了,这时关闭80端口。但此时客户端发信息的时候必然是发向80断口,但是80已经关了啊,但是通信依然正常进行。其实我刚接触套接字的时候也是认为所有从客户端发来的数据都需要经过监听套接字转一下才能收到。所有的初学者都容易犯这个误解。
经过一段时间的使用,我现在是明白了,监听套接字就是个牵线指路的,你实质上是跟它指的那个人说话。因为你要找的那个人不可能随时等你来,而监听套接字就是专职等你来问,它回答你要找的人在哪,并唤醒你要找的人,于是通话就建立起来了,就像现实生活中的接线员一样。
也就是说,在连接建立后,客户端用发出连接的那个SOCKET向服务器发数据,是发给服务器新创建的SOCKET,而不是服务器的监听SOCKET。服务器的监听SOCKET永远只是用来接受连接请求。
这就好比你去吃饭,饭馆门口有迎宾***(监听SOCKET)看到你来后和你打招呼,然后(ACCEPT)找来一个新的服务员(NEW SOCKET)来接待你,然后守在门口继续监听下一个。监听的***走了,接待你的服务员当然不受影响。
说到这里有必要说一下accept()函数。以下是《Linux网络编程》一书,第六章 Berkeley套接字对accept()函数的描述:
函数 accept()有一些难懂。当调用它的时候,大致过程是下面这样的:
● 有人从很远很远的地方尝试调用 connect()来连接你的机器上的某个端口(当然是你已经在 listen()的)。
● 他的连接将被 listen 加入等待队列等待 accept()函数的调用(加入等待队列的最多数目由调用 listen()函数的第二个参数 backlog 来决定)。
● 你调用 accept()函数,告诉他你准备连接。
● accept()函数将回返回一个新的套接字描述符,这个描述符就代表了这个连接!
好,这时候你有了两个套接字描述符,返回给你的那个就是和远程计算机的连接,而第一个套接字描述符仍然在你的机器上原来的那个端口上 listen()。
这时候你所得到的那个新的套接字描述符就可以进行 send()操作和recv()操作了。
通过上面的解释,相信您一定已经对监听套接字有了进一步的了解了吧!
转自: