【问题标题】:Sys/socket concurrency for non-blocking?非阻塞的系统/套接字并发?
【发布时间】:2017-02-10 10:01:12
【问题描述】:

我有一个使用 sys/socket 和 OpenSSL 设置的简单套接字服务器。对于每个连接,客户端都需要向服务器发送消息,接收响应,然后回复该响应。

我找不到任何明确的机制来使这些套接字成为非阻塞的?系统必须能够同时处理多个套接字...

我用于监听连接的服务器代码:

while(1)
{
   struct sockaddr_in addr;
   uint len = sizeof(addr);
   SSL *ssl;            
   int client = accept(sock, (struct sockaddr*)&addr, &len);
   if (client > 0) 
   {
      std::cout<<"Client accepted..."<<std::endl;
   }
   else
   {
      perror("Unable to accept");
      exit(EXIT_FAILURE);
   }

   ssl = SSL_new(ctx); 
   SSL_set_fd(ssl, client);

   if (SSL_accept(ssl) <= 0)
   {
      std::cout<<"ERROR"<<std::endl;
   }
   else
   {
      char buff[1024];
      SSL_read(ssl, buff, 1024);
      std::cout<<buff<<std::endl;

      std::string reply="Thanks from the server";
      char buff_response[1024];
      reply.copy(buff_response, 1024);
      const void *buf=&buff_response;
      SSL_write(ssl, buf, 1024);

      char another_buff[1024];
      SSL_read(ssl,another_buff,1024);
      std::cout<<another_buff<<std::endl;
   }
}

我查看了“select()”,但这似乎不允许并发,但允许系统知道何时释放套接字?

有人有解决这个基本问题的经验吗?

【问题讨论】:

  • 我认为你应该再看看 select 。它不是关于释放套接字,而是关于检测是否有新数据可用以及是否可以写入数据,即正是你需要的。由于 SSL 套接字和选择比普通套接字和选择要复杂一些,我建议您从更简单的情况开始,然后在研究 How to handle OpenSSL SSL_ERROR_WANT_READ / WANT_WRITE on non-blocking sockets 和其他资源之后添加 SSL。
  • 您不需要非阻塞模式来同时处理多个客户端,并且O_NONBLOCK机制定义得非常好。不清楚你在问什么。

标签: c++ sockets


【解决方案1】:

首先,对于服务器代码,differentiate between concurrency and parallelism 很重要。一个合理的服务器通常会处理many more connections concurrently than its number of cores。因此,重要的是使代码并发,因为它可以(有效地)以不依赖于并行性的方式(在某种意义上)处理许多并发连接让每个连接都由一个线程处理)。

从这个意义上讲,select实际上是一个合理的并发选择,并给你the effect of being non-blocking

当您的系统同时处理多个套接字时,select 指示您可以在哪些套接字上执行sendrecv 等操作而不会阻塞。如果您使用select,您将不会出现线程空闲、无限期地等待某些操作继续进行而其他套接字已准备好的情况。

minimal example from gnu.org 显示了一个相当高效的服务器,您似乎可以根据自己的需要进行调整。

fd_set active_fd_set, read_fd_set;
FD_ZERO (&active_fd_set);
FD_ZERO (&read_fd_set);

// Use FD_SET to add sockets according to what you want to do with them

/* This call (checking to see who can be read) is the 
* only thing that blocks. But if it does, no socket is ready for reading. */
if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0) {
    // Handle error;

for (i = 0; i < FD_SETSIZE; ++i)
    if (FD_ISSET (i, &read_fd_set))
        // Here you can read without its blocking.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-31
    • 2013-10-15
    • 1970-01-01
    • 2013-06-03
    • 1970-01-01
    • 1970-01-01
    • 2014-05-27
    • 1970-01-01
    相关资源
    最近更新 更多