【问题标题】:Multiple threads writing to same socket causing issues多个线程写入同一个套接字导致问题
【发布时间】:2014-08-01 19:16:00
【问题描述】:

我编写了一个客户端/服务器应用程序,其中服务器根据来自客户端的请求生成多个线程。

这些线程应该向客户端(字符串)发送一些数据。

问题是,数据在客户端被覆盖。我该如何解决这个问题?

我已经阅读了一些关于类似问题的其他主题,但无法找到确切的解决方案。

这是我接收数据的客户端代码。

while(1)
    {
            char buff[MAX_BUFF];
            int bytes_read = read(sd,buff,MAX_BUFF);
            if(bytes_read == 0)
            {
                    break;
            }
            else if(bytes_read > 0)
            {
                    if(buff[bytes_read-1]=='$')
                    {
                            buff[bytes_read-1]='\0';
                            cout<<buff;
                    }
                    else
                    {
                            cout<<buff;
                    }
            }
    }

服务器线程代码:

void send_data(int sd,char *data)
{
    write(sd,data,strlen(data));
    cout<<data;
}

void *calcWordCount(void *arg)
{
    tdata *tmp = (tdata *)arg;
    string line = tmp->line;
    string s = tmp->arg;
    int sd = tmp->sd_c;
    int line_no = tmp->line_no;
    int startpos = 0;
    int finds = 0;
    while ((startpos = line.find(s, startpos)) != std::string::npos)
    {
            ++finds;
            startpos+=1;
            pthread_mutex_lock(&myMux);
            tcount++;
            pthread_mutex_unlock(&myMux);
    }
    pthread_mutex_lock(&mapMux);
    int t=wcount[s];
    wcount[s]=t+finds;
    pthread_mutex_unlock(&mapMux);


    char buff[MAX_BUFF];
    sprintf(buff,"%s",s.c_str());
    sprintf(buff+strlen(buff),"%s"," occured ");
    sprintf(buff+strlen(buff),"%d",finds);
    sprintf(buff+strlen(buff),"%s"," times on line ");
    sprintf(buff+strlen(buff),"%d",line_no);
    sprintf(buff+strlen(buff),"\n",strlen("\n"));
    send_data(sd,buff);
    delete (tdata*)arg;
}

【问题讨论】:

  • 贴出服务器线程代码...
  • “问题是,数据在客户端被覆盖。” - 这不太可能。 “覆盖*”更有可能发生在服务器端。
  • @StephenC 实际上,来自不同线程的数据似乎是由 TCP 一起发送的。
  • 为什么写入缓冲区的代码以及随后对send_data() 的调用不受互斥锁的保护?那是你依赖的原子数据,不是吗?
  • 是的,但我尝试通过保护该呼叫..仍然没有好处..

标签: c++ c multithreading sockets pthreads


【解决方案1】:

你应该在你的套接字上放一些互斥锁。

当线程使用套接字时,它应该阻塞套接字。

一些mutex 的例子。

如果没有服务器代码,我无法为您提供更多帮助。因为问题很可能出在服务器上。

【讨论】:

  • 我已经在 write 调用中尝试过互斥锁。但这也行不通.. :(
【解决方案2】:
  1. 在服务器端确保共享资源(套接字及其关联的内部缓冲区)受到保护,防止并发访问。
  2. 定义并实现服务器使用的应用程序级协议,使客户端能够区分不同线程发送的内容。

另外说明: 不能依赖read()/write() 读取/写入与这两个函数被告知读取/写入一样多的字节。检查它们的返回值以了解这些函数实际读/写了多少字节并围绕它们循环直到所有打算读/写的数据都被读/写是必不可少的。

【讨论】:

  • 应用层协议会有帮助吗? bcoz,底层网络协议将始终是 TCP,我认为这会导致问题。我觉得由于更多的数据量可以放入单个 TCP 段中,因此来自每个线程的数据..我遇到了问题。
  • 每个线程都有不同的缓冲区。我还需要保护它吗?
  • 套接字内部正好有一个缓冲区,由对write()的调用填充。所以第一保护对后者的访问。 @Ajit
  • 应用层协议肯定会有所帮助,因为它会在原始网络数据之上添加一些额外的逻辑层,这将允许您确定您是否拥有所需的所有数据,它是正确的,以及它来自哪里。 TCP 将确保您的数据包正确发送和接收,但不会确保每个数据包都符合您的预期,并且包含您的数据集的所有数据包在发送之前都已正确填写。
  • pthread_mutex_lock(&thMux);发送数据(SD,buff); pthread_mutex_unlock(&thMux);不过这对我没有帮助.. 为这么小的任务编写应用程序级协议.. :(.. 让我试试看.. :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-10
  • 2023-03-19
  • 1970-01-01
  • 2013-11-21
  • 2012-05-17
  • 2018-11-24
相关资源
最近更新 更多