客户端,多线程中全局同一个socket,调用问题

superymq 2007-10-02 05:17:02
客户端就一个socket,connect server,然后保持长连接
请问师傅们:
多线程send()时,用加锁不?
一线程select()检测可读socket,另一线程想send()完就recv(),这两谁先响应,会不会有异常呢

我现在就想如果真有这么多事,我就只在一处send,recv得了

或者多线程这种设计就不对,也请您给我个思路,谢谢~
...全文
955 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
arong1234 2007-10-05
  • 打赏
  • 举报
回复
多线程共享socket会导致严重问题

1. 当多线程同时发送报文时,由于发送不是原子的,对方接收到的报文将是混乱的
例如线程1发送"abcd"
线程2发送"1234",对方收到的可能是a123bc4d

2. 当线程接收时,由于一次发送不对应一次接收,将导致你无法处理

例如对方发送两个报文"abcd", "1234"
一个线程可能接收到"abcd1",另外一个则收到"234",那么这样的报文你怎么处理?

所以这不是并发控制问题,而是根本不能这么用
arong1234 2007-10-05
  • 打赏
  • 举报
回复
5楼:我说的不是说单线程就不会有2次send3次recv的问题,这种send和recv次数问题是流式套接字特有的,任何方法都无法避免(大家都叫他粘包,我也这么叫吧,虽然我不是很喜欢这种称呼)你上面得消息头机制是一种必须得方法去处理次问题

我说的是乱包的问题,由于粘包问题的存在,你必须锁住一个线程直到他锁需要发送的东西全部发送出去才可以释放锁,那么将造成许多问题。

你说的“理论上没问题”是正确的,但是这种实现是很难具有可操作性的,这要求设计者以及相关模块的程序员都必须对socket和线程都有非常深刻的了解,而这往往很难做到。我说“根本不能这么用”,是从代价上考虑的,为了一个虚无飘渺的每个线程都可以发送,程序员得付出多少?项目会有多少延期?经理要骂多少次娘?

理论上怎样有时没有啥意义。

好得设计必须确保模块隔离。对于socket,我得建议是发送和接收都分别是一个线程(对于CAsyncSocket不适用,因为他们依赖CSocketWnd,而后者只能在一个线程里用),需要发送得线程通过队列丢给socket发送线程,发送者不等待;而接收线程收到完整报文后,通过线程间消息或者线程共享队列给其他线程处理。这样才是最安全得。
晨星 2007-10-05
  • 打赏
  • 举报
回复
不太同意楼上所说,即使单个线程使用socket,对于流式套接字来说,也仍能可能发生诸如发送方两次send的数据,接收分三次才能recv下来的事情,所以,这个不可以依靠单线程来保证,而必须制定详尽的应用层的报文格式。比如规定一个消息的前4个字节是一个由消息标志和消息长度组成的消息头,这样接收方每次可以先把消息头收下来,然后根据消息头中的消息长度决定如何接收后续的信息。

所以加锁理论上是没有问题的。问题是这样的锁实际上可能很复杂,尤其是对一个socket又读又写的时候,会搞得程序暴难维护。所以尽量还是不要这么做。
dyw 2007-10-04
  • 打赏
  • 举报
回复
就一个socket,有必要多线程吗?不要为了多线程而多线程。
coldplay968 2007-10-02
  • 打赏
  • 举报
回复
为什么要公用 socket呢?
晨星 2007-10-02
  • 打赏
  • 举报
回复
多个线程共享一个socket,肯定要加锁的。
一般在网络编程中使用多线程,通常要么是多个工作线程各自使用自己的socket,要么就是只有一个通讯线程用socket,而另外的线程只是产生或处理数据。

18,357

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧