关于send是否会造成数据乱序的有关问题
关于send是否会造成数据乱序的问题
刚看了关于这个问题的帖子,但有些问题想问明白些,前面的问题是说多线程下
send会不会使得包乱序,我认为会乱序。是这样的,有人回复了send的原理,
send只是把数据copy到发送缓冲区。并且send时先检查send的大小slen和发送缓
冲区bufLen大小,如果slen > bufLen 就直接返回SOCKET_ERROR,否则再检查缓
冲区是否在发送数据,如果缓冲区在发送数据则等待发送完,如果协议还没有发
送数据则检查缓冲区剩余大小sblen,if(slen>sblen)send会一直等待协议把数据
发送完,否则send就把数据copy到缓冲区,如果copy时发生错误返回
SOCKET_ERROR,(第一个问题在这里:造成COPY发生错误的原因有哪些)。以上描
述,个人认为send会造成包的乱序,在不同的线程里send,就算你比我先send,但
由于线程切换,我也有可能比你先一步到达目的地。这里不知道说得对不对,假
如这个说法成立的话,如果你在不同的线程里send没有一次性发送完整的包,那
更可怕的事情就来了,就不是粘包的问题了,这是数据真正错乱了,在另一端收
到后你无法取出完整的包!!具体描述是这样的,线程A半个包到达目的地,线
程B半个包到达目的地,线程A半个包到达目的地,线程B半个包到达目的地……
,不知道是不是这样子的。如果有不对希望哪位大侠指正一下。也同时希望大家
多多讨论一下。谢谢!!!
------解决方案--------------------
tcp/ip协议栈里,本身就带了锁保护
当你用几个线程同时使用send进行发送
实际上只是对本地的socket发送缓冲进行带锁的写操作
实现:
CCriticalSection m_lock
char * m_sndbuff;
size_t i_buffsize;
size_t i_buffremain;
任何一个线程的send 调用
实际都转换成
m_lock.Lock( );
if(datasize<=buffremain)
{
memcpy(m_sndbuff+i_buffsize-buffremain,pnewdata,datasize);
m_lock.Unlock( );
return datasize;
}
m_lock.Unlock( );
return SOCKET_ERROR; //-1 or 0
至于协议栈里的m_sndbuff
它的发送次序你应用层是无法修改的,因此只要你的send成功
那么次序就被确定了
不会出现这个线程的send拷贝了一半数据然后被另一个线程中断,执行另一个线程的数据拷贝
没有这种可能的,底层实现是带了锁保护的
刚看了关于这个问题的帖子,但有些问题想问明白些,前面的问题是说多线程下
send会不会使得包乱序,我认为会乱序。是这样的,有人回复了send的原理,
send只是把数据copy到发送缓冲区。并且send时先检查send的大小slen和发送缓
冲区bufLen大小,如果slen > bufLen 就直接返回SOCKET_ERROR,否则再检查缓
冲区是否在发送数据,如果缓冲区在发送数据则等待发送完,如果协议还没有发
送数据则检查缓冲区剩余大小sblen,if(slen>sblen)send会一直等待协议把数据
发送完,否则send就把数据copy到缓冲区,如果copy时发生错误返回
SOCKET_ERROR,(第一个问题在这里:造成COPY发生错误的原因有哪些)。以上描
述,个人认为send会造成包的乱序,在不同的线程里send,就算你比我先send,但
由于线程切换,我也有可能比你先一步到达目的地。这里不知道说得对不对,假
如这个说法成立的话,如果你在不同的线程里send没有一次性发送完整的包,那
更可怕的事情就来了,就不是粘包的问题了,这是数据真正错乱了,在另一端收
到后你无法取出完整的包!!具体描述是这样的,线程A半个包到达目的地,线
程B半个包到达目的地,线程A半个包到达目的地,线程B半个包到达目的地……
,不知道是不是这样子的。如果有不对希望哪位大侠指正一下。也同时希望大家
多多讨论一下。谢谢!!!
------解决方案--------------------
tcp/ip协议栈里,本身就带了锁保护
当你用几个线程同时使用send进行发送
实际上只是对本地的socket发送缓冲进行带锁的写操作
实现:
CCriticalSection m_lock
char * m_sndbuff;
size_t i_buffsize;
size_t i_buffremain;
任何一个线程的send 调用
实际都转换成
m_lock.Lock( );
if(datasize<=buffremain)
{
memcpy(m_sndbuff+i_buffsize-buffremain,pnewdata,datasize);
m_lock.Unlock( );
return datasize;
}
m_lock.Unlock( );
return SOCKET_ERROR; //-1 or 0
至于协议栈里的m_sndbuff
它的发送次序你应用层是无法修改的,因此只要你的send成功
那么次序就被确定了
不会出现这个线程的send拷贝了一半数据然后被另一个线程中断,执行另一个线程的数据拷贝
没有这种可能的,底层实现是带了锁保护的