设计具有非阻塞管道转发到另一台服务器的代理

时间:2017-03-05 06:27:42

标签: c pipe ipc iperf

我写了一个代理,它也复制了流量。我正在尝试将网络流量复制到副本服务器,该服务器应该接收所有输入并处理所有请求。但是,只有主服务器上的响应对客户端可见。高级工作流程如下

Thread 1. Take input from client forward it to a pipe in non-blocking way, and to the server
Thread 2. Read from server and send to client
Thread 3. Read from pipe and forward to replica server
Thread 4. Read from replica server and drop

这个代码可以在这个要点中找到:https://gist.github.com/nipunarora/679d49e81086b5a75195ec35ced646de

测试似乎适用于较小的数据和事务,但在使用iperf和更大的数据集时,我似乎遇到以下错误:

Buffer overflow? : Resource temporarily unavailable

问题源于的代码中的特定部分:

void forward_data_asynch(int source_sock, int destination_sock) {
  char buffer[BUF_SIZE];
  int n;

  //put in error condition for -1, currently the socket is shutdown
  while ((n = recv(source_sock, buffer, BUF_SIZE, 0)) > 0)// read data from input socket 
    { 
      send(destination_sock, buffer, n, 0); // send data to output socket
      if( write(pfds[1],buffer,n) < 0 )//send data to pipe
        {
          //fprintf(stats_file,"buffer_overflow \n");
          //printf("format string" ,a0,a1);
          //int_timeofday();
          perror("Buffer overflow? ");
        }
      //DEBUG_PRINT("Data sent to pipe %s \n", buffer);
    }

  shutdown(destination_sock, SHUT_RDWR); // stop other processes from using socket
  close(destination_sock);

  shutdown(source_sock, SHUT_RDWR); // stop other processes from using socket
  close(source_sock);
}

阅读过程如下:

void forward_data_pipe(int destination_sock) {

  char buffer[BUF_SIZE];
  int n;
  sleep(10);
  //put in error condition for -1, currently the socket is shutdown
  while ((n = read(pfds[0], buffer, BUF_SIZE)) > 0)// read data from pipe socket 
    { 
      //sleep(1);
      //DEBUG_PRINT("Data received in pipe %s \n", buffer);
      send(destination_sock, buffer, n, 0); // send data to output socket
    }

  shutdown(destination_sock, SHUT_RDWR); // stop other processes from using socket
  close(destination_sock);
}

请注意,管道的定义如下:

/**   Make file descriptor non blocking */
int setNonblocking(int fd)
{
  int flags;

  /* If they have O_NONBLOCK, use the Posix way to do it */
#if defined(O_NONBLOCK)
  /* Fixme: O_NONBLOCK is defined but broken on SunOS 4.1.x and AIX 3.2.5. */
  if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
    flags = 0;
  return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
#else
  /* Otherwise, use the old way of doing it */
  flags = 1;
  return ioctl(fd, FIOBIO, &flags);
#endif
}   

任何人都可以帮忙解决可能导致错误的原因吗?

1 个答案:

答案 0 :(得分:0)

您遇到的问题是数据发送得太快,无法设置为非阻塞模式的套接字。您有几种选择:

  1. 接受数据可能丢失的事实。如果您不想延迟主服务器上的处理,这是您唯一的选择。
  2. 不要将套接字设置为非阻塞模式。如果您不希望数据丢失,默认模式,阻止,似乎更适合您的应用程序。但是,这也意味着系统可能会变慢。
  3. 使用poll(),select(),kqueue(),epoll(),/ dev / poll或类似命令,等待套接字有足够的可用缓冲区空间。但是,在使用它时,您应该考虑为什么首先将套接字设置为非阻塞模式,如果您仍希望阻止它。这也会导致系统放缓。