现需要多线程(不妨设为Thread1和Thread2)操作一个网络套接字(Sock)。例如:Thread1调用send(Sock,"abcd",...)函数发送数据同时Thread2也在调用send(Sock,"1234",...),问是否会出现程序逻辑上的错误。这里的逻辑错误是指当程序在另一端调用recv时候收到的序列有没有可能是"ab1234cd"或是"1abc234d",而不是想要的"abcd1234"或者"1234abcd"?
本人也在网上看过有人问到这样的问题,解决方法大都是在发送端建立一个队列,Thread1和Thread2先后分别将数据先放入队列中,然后只用一个线程操作发送套接字Sock发送队列中的数据,这当然可以解决上述问题。
但本人也在网上看到有人解释send函数原理的时候说到:
“这里只描述同步Socket的send函数的执行流程。当调用该函数时,send先比较待发送数据的长度len和套接字s的发送缓冲的 长度,如果len大于s的发送缓冲区的长度,该函数返回SOCKET_ERROR;如果len小于或者等于s的发送缓冲区的长度,那么send先检查协议是否正在发送s的发送缓冲中的数据,如果是就等待协议把数据发送完,如果协议还没有开始发送s的发送缓冲中的数据或者s的发送缓冲中没有数据,那么 send就比较s的发送缓冲区的剩余空间和len,如果len大于剩余空间大小send就一直等待协议把s的发送缓冲中的数据发送完,如果len小于剩余空间大小send就仅仅把buf中的数据copy到剩余空间里”,原文出处:http://hi.baidu.com/webeta/blog/item/4c04d109fdf21881d1581be8.html按照上述解释,也就是说,send函数要么一次性全部将数据拷贝到协议的发送缓冲区,要么一直阻塞不拷贝,直到发送缓冲区空闲空间大于要发送的数据大小。如此解释分析可知不会出现"ab1234cd"或是"1abc234d",而只能是"abcd1234"或者"1234abcd"。也没必要在发送端建立一个队列。
不知send函数的内部具体原理如何,在这里也请哪位熟知send和recv内部原理的朋友告知,感激不尽!

解决方案 »

  1.   

    应该不用考虑,send首先读的是包头size然后是拷贝buf指针,recv也是,只有数据包可能出现分包的时候要考虑。
      

  2.   

    楼上可将send原理再说详细点不?
      

  3.   

    send函数用于tcp的可靠性连接,由于它是基于流的形式发送的,所以无论你发送的数据多大,它都会帮你发送出去;协议栈的确帮你暂存了数据,真正的发送工作也的确是有协议栈发送出去的,超过了它的大小,不一定就发送失败,可能它会帮你发送一部分;send分为阻塞和非阻塞
    阻塞的情况:send函数之所以阻塞着,是地层的协议栈不断地拷贝你要发送的数据[数据大的时候才不断地拷贝]然后一部分一部分发送出去,完成了它就继续往下执行[不用在阻塞了],我们说发送要规定数据包的大小,那个一般是对于udp的数据包发送,为了减轻系统的负担,一次性完成的操作,而TCP却不是的.非阻塞的情况:send函数不阻塞,很多开发网络的朋友都会这样发送数据while(){send();},直到数据发送完成,判断每次send出去的数据是否已经达到了要发送的数据大小了,发完则退出,为什么呢?的确是协议栈不够大而已,但是它不会失败的
      

  4.   

    Thread1调用send(Sock,"abcd",...)函数发送数据同时Thread2也在调用send(Sock,"1234",...),问是否会出现程序逻辑上的错误。这里的逻辑错误是指当程序在另一端调用recv时候收到的序列有没有可能是"ab1234cd"或是"1abc234d",而不是想要的"abcd1234"或者"1234abcd"? 
    不可能出现这种情况
      

  5.   

    要看实现,参阅:tcp/ip 三巨头的第二巨头: tcp/ip 实现
      

  6.   

    Thread1调用send(Sock,"abcd",...)函数发送数据同时Thread2也在调用send(Sock,"1234",...),问是否会出现程序逻辑上的错误。这里的逻辑错误是指当程序在另一端调用recv时候收到的序列有没有可能是"ab1234cd"或是"1abc234d",而不是想要的"abcd1234"或者"1234abcd"? 绝对会出现这种情况!因为 send 不是原子操作,把buf中的数据copy到剩余空间也不是,就像多线程操作同一内存的情况。
      

  7.   

    不用系统的TCP/IP协议栈的具体实现方式是不一样的,但是基本原理都是一样的,协议格式更是一样的。如果你非常希望了解他的原理,建议你下载LWIP看下,有文档,全代码,非常适合做你的教材。
      

  8.   

    我觉得不应该两个线程同时操作一个SOCKET