【问题标题】:Sending while receiving in C在C中接收时发送
【发布时间】:2014-06-23 12:34:25
【问题描述】:

我已经在我的服务器上编写了一段代码作为多个线程

问题是当我在另一个套接字上接收时它不发送数据。

所以如果我从客户端 1 向客户端 2 发送一些东西,客户端 2 只有在他自己发送一些东西时才会收到(跳出 recv 函数).. 我该如何解决这个问题?

 /* Thread*/
while (! stop_received) {
        nr_bytes_recv = recv(s, buffer, BUFFSIZE, 0);

        if(strncmp(buffer, "SEND", 4) == 0) {
            char *message = "Text asads \n";
            rv = send(users[0].s, message, strlen(message), 0);
            rv = send(users[1].s, message, strlen(message), 0);
            if (rv < 0) {
                perror("Error sending");
                exit(EXIT_FAILURE);
            }           
        }else{
            char *message = "Unknown command \n";
            rv = send(s, message, strlen(message), 0);
            if (rv < 0) {
                perror("Error sending");
                exit(EXIT_FAILURE);
            }
        }
}

【问题讨论】:

    标签: c sockets blocking


    【解决方案1】:

    更具体地说,有几种类型的 I/O。您当前正在做的事情称为阻塞 i/o。一般来说,这意味着当您调用sendrecv 时,操作将“阻塞”直到完成。

    与此相反,有所谓的非阻塞 i/o。在这个 i/o 模型中,如果操作无法完成,它将立即返回。通常select 函数与此 i/o 模型一起使用。

    您可以在Select Tutorial 上查看示例程序。完整的源代码在页面底部。

    正如其他人所指出的,您的另一个选择是使用线程。

    【讨论】:

      【解决方案2】:

      您的代码将阻止recv() 调用。要么编写一个多线程应用程序,要么研究select() 函数的使用。

      【讨论】:

        【解决方案3】:

        将发送和接收放在不同的线程中。

        【讨论】:

          【解决方案4】:

          我注意到您使用的是perror()(POSIX 错误函数),这让我相信您使用的是 POSIX 操作系统,这让我怀疑它是 GNU/Linux。

          select() 是可移植的,poll() 以 POSIX 为中心,epoll() 以 Linux 为中心。如果使用 GNU/Linux,我强烈建议避免使用 select() 并使用:

          • poll() 如果您只轮询几十个文件描述符
          • epoll() 如果您需要扩展到数千个连接,并且它可用。

          如果您的应用程序不需要可移植,并且没有要求禁止使用扩展,请使用poll()epoll()。一旦您了解了 select() 的工作原理,您将很高兴摆脱它,尤其是对于必须扩展以服务于许多客户的东西。

          如果需要可移植性,请查看在构建配置期间是否存在poll()epoll(),并使用其中一个来支持select()

          注意,epoll() 直到 Linux 2.5(something) 才出现,所以最好习惯使用两者。

          【讨论】:

          【解决方案5】:

          你应该把代码分成两个线程,一个发送器和一个接收器。

          类似这样的:

           /* 1st Thread*/
          while (! stop_received) {
                  nr_bytes_recv = recv(s, buffer, BUFFSIZE, 0);
          }
          
          
           /* 2nd Thread*/
          while (! stop_received) {
                  if(strncmp(buffer, "SEND", 4) == 0) {
                      char *message = "Text asads \n";
                      rv = send(users[0].s, message, strlen(message), 0);
                      rv = send(users[1].s, message, strlen(message), 0);
                      if (rv < 0) {
                          perror("Error sending");
                          exit(EXIT_FAILURE);
                      }           
                  }else{
                      char *message = "Unknown command \n";
                      rv = send(s, message, strlen(message), 0);
                      if (rv < 0) {
                          perror("Error sending");
                          exit(EXIT_FAILURE);
                      }
                  }
          }
          

          并发会带来一些问题,比如访问buffer变量。

          【讨论】:

            【解决方案6】:

            有两种方法可以实现你想要的目标:

            1.) 在不同的线程中实现发送和接收代码。但是会有一些问题,比如增加客户端数量可能会让你在处理代码时遇到麻烦。还会有一些并发问题(正如 pcent 所提到的)。 你可以选择无阻塞套接字,但我建议不要这样做,因为我希望你不想要一个 cpu hog。

            2.) 另一种方法是使用 select() 函数,它可以让您同时监控多个不同类型的套接字。有关“select()”的更多描述,您可以谷歌它。 :)

            【讨论】:

              猜你喜欢
              • 2016-07-28
              • 2010-12-22
              • 2017-09-04
              • 1970-01-01
              • 1970-01-01
              • 2013-04-01
              • 2011-07-26
              • 2012-08-10
              • 2018-08-30
              相关资源
              最近更新 更多