近日,写了个局域网内的 “服务器-客户端” 程序(都是linux的),我写的是服务端,客户端另外两个人写。
    然后出现了个问题,数据经常不正确,后来,我帮他找到了问题,他们那边多线程使用同一个SOCKET进行发送数据,没加互斥,导致了数据交错。 然后那人就跟我说了,你程序应该判断这个数据是那个线程发过来的啊,说我的程序兼容性不好。
    然后还给我讲了好多好多的网络编程技术(他说他以前是做4G网络通讯设备开发的,跟我讲TCP包头,IP包头什么的),其中有个关键点就是,2个程序之间TCP连接的时候,一方程序关闭或者电脑关闭或者拔掉网线,另一方是不知道的,发送方还可以继续发送数据,因为发送方只是将数据放入本地缓存中,并不知道也不管对方在不在, 所以,需要心跳包来维持TCP连接,根据心跳包丢失数量来确认网络已断,(我们之间是有做了心跳包的,一定时间内收不到他的数据,就会踢掉客户端),等等等等,跟我扯了半个多小时,指出我好多好多的错误,最后,跟我讲,这个互斥,我们这边可以加一下。
   其他我都无所谓了,有一点“一方程序关闭或者电脑关闭或者拔掉网线,另一方是不知道”,如此地贬低TCP,我就不开心了,Stevens叔叔的《TCP/IP详解》的三卷我也粗粗地过了2遍了,虽说第二卷好些地方看不懂,但是我还是很相信TCP的可靠性的,我相信TCP不至于这么鸡肋,然后就写了个测试客户端程序跟我的程序进行通讯(个人习惯用VS,就拿VS写了一个客户端),经测试任意一方关闭程序,对方马上就可以知道啊,然后他跟我说,WINDOWS可以,linux不行;我就把测试客户端程序改了一下,linux下运行也是一方关闭另一方马上知道啊,然后他跟我说,拔网线肯定对方不知道,我要不要拔一下网线试试呢? 跟我讲网络编程知识的是我们部门大领导啊,我敢不敢再测一下拔网线呢?

解决方案 »

  1.   

    哈哈哈 ,那你要让你的领导重新学习一下tcp协议了
      

  2.   

    我试了一下强制关闭(kill -9)netcat的TCP连接,答案是kernel会自动发送FIN,ACK包正常结束连接,所以楼主前面的测试结果是正确的。
    但设想一下拔网线的情况,这时是不可能有FIN,ACK包发出来的,所以双方都不会知道连接已经丢失,这时候一般是重传数次,然后报错。这个就不演示了,楼主可以用wireshark自己实验一下。
      

  3.   

    1. 正常的断线,无论是拔网线还是主动断掉,肯定双方都可以检测到的
    2. 有一种情况可能检测不到,就是从链路层断开连接了,这个必须通过设置心跳包来自动管理
    3. 判断数据从哪个线程过来,这个明显属于应用层面的工作了。你们定义一个简单的交互协议就可以解决了(比如带上一个唯一的ID之类的),同TCP通讯没有关系的。
      

  4.   


    拔掉网线的时候,send的确没有返回失败,但是,dmesg 显示了好多的”found a client with no channel in the client's hash table",说明系统是知道拔掉网线了,现在的问题是程序如何获取到这个消息呢
      

  5.   

    可能是防火墙的原因。TCP依赖于网络的硬件可靠性。
      

  6.   

    对不起,操作失误,多发了一次:
    1.如果是拔掉的是你的计算机和交换机之间的网线,而对方的网线正常,那么对方确实是不知道
    2.如果是你的进程关闭的话,对方应该会收到网络断开命令的
    3.如果进程被任务管理器强制关闭的话,不知道对方是否会知道,但我想可能会知道的吧(我不确定的)
    4.TCP通讯是应该做心跳的