考虑到以后可能要用到服务器程序,如果没有现成的、稳定的代码,到时候可能会遇到麻烦。所以,最近一有空,就写服务器的框架代码。
问题一:select模型如何得知连接中断?
select模型只有三种套接字集合:发送、接收、异常。那么,怎么知道远程客户端中断了网络连接呢?跟踪调试发现,当远程客户端主动中断连接时,服务器接收到长度为0的数据包。
这一点很好理解。因为TCP连接中断时,客户端和服务器会相互发送通知数据包。这个数据包没有内容,只有TCP/IP报头。所以,内容长度为0,这是可以理解的。
于是,在接收到长度为0的数据包时,可以认为,这是远程客户端中断了连接。——但是,在网络上找到的代码,里面都没有对远程客户端主动中断连接进行处理,所以,我无法验证自己的看法是否正确。
另外,对于TCP连接,还有一种数据包的长度为0,即“心跳数据包”。和UDP不同,TCP是基于连接的。这种基于连接的协议,它的实现其实并不复杂。TCP会定时发送“心跳数据包”,通过这个数据包来保持两台主机之间的连接性。
假设,客户端发送了多次“心跳数据包”,服务器始终没有响应,那么,说明连接可能中断了;反之,表示连接仍然保持着。这就是“面向连接”。
可以猜想,这种心跳数据包应该也是长度为0的吧,那它不是和连接关闭的数据包相互混淆了?那到底该怎么判断客户端主动关闭了连接?
问题二:select模型为什么无缘无故地要求发送数据?
客户端连接服务器之后,什么事情都没做,但是select的结果是发送数据包!不向服务器发送数据包还不行!可能是哪句代码弄错了?
我想,可能在TCP连接成功建立之后,客户端是应该马上发送数据包给服务器的。但是,我之所以这么做,是因为曾经截获过HTTPS协议的数据包。如果我没有记错的话,HTTPS在TCP连接建立之后,服务器会向客户端发送一个数据包,也就是SSL的加密密钥。
这么说来,连接建立之后,客户端是可以不发送数据的吧?那为什么select模型总是提示客户端应该发送数据包?
20110916注:
问题一的答案:
在TCP连接中断时的四次挥手中,会触发上层应用程序接收数据,此时收到的是0字节的数据包,据此可以判断连接中断。
问题二的答案:
select模型,在连接建立后,触发事件并提示可以发送数据包,此时,表示网卡空闲,可以发送数据包。我们此时可以发送,也可以不发送。这里的“要求发送”只是一种通知,等同于说,这里有空座位,你可以去坐,也可以不坐。