总会看到c++新手写网络通讯时,不理解recv()为什么阻塞或不阻塞,TCP数据顺序会不会乱,UDP会不会数据包不完整,都是对TCP/IP协议原理没有基本常识导致的。
我曾看到代码,客户端recv(buf, 31), 实际服务器只会发送4个字节,客户端将永远阻塞,直到服务器主动close()为止。
开始时那个服务器是实现一请求一应答,答应后立即关闭,所以客户端没有事。
后来服务器维护者,感觉要支持一个连接上支持一个或多个请求,就修改成等待客户端自己关闭或网络异常,服务器才关闭socket。这个修改看来是正常的,因为服务器一般写法都是被动关闭的,关闭权在客户端。可是这么一修改,原来那个客户端就阻塞死了,用户莫名其妙。
这里有一个有趣现象:如果服务器维护者不修改,那么那个客户端软件一直是可以正常运行的,但从我们开发者角度来看,明明是一种实现错误,至少是缺陷吧。可是,测试人员黑盒测试是不可能测试出来的,一般测试人员也不会去写代码测试,所以这种问题测试组搞不定。
很多时候,在测试环境里没问题,在真实环境就出现一些古怪的问题,其实问题不古怪。
比如:A通过TCP向B发送1024字节,B采用一次性接收recv(buf, 1024), 测试环境常常每次都是一次收满,包是完整的;在真实环境,A和B在不同地域,之间不知道多少交换机和路由器,那可能就第一次只收到500字节,如果不加判断返回值乱处理,问题就出来了。
这个问题还不止一次看到新手这么干。