如何修改recv以实现IO /非阻塞?

时间:2012-05-29 16:26:40

标签: c nonblocking asyncsocket recv

我试图在C中编写服务器,I / O无阻塞,因为有时它会因洪水请求而关闭。 环顾四周,我注意到I / O非阻塞可以解决我的问题。 阅读Beej指南,我实现了recvtimeout函数,该函数设置超时以处理来自客户端的数据。 人们告诉我,我必须使用选择来避免这个问题,但我已经在函数recvtimeout中使用了它:

int Server::recvtimeout(int s, char *buf, int len, int timeout)
    {

    //Check if non-blocking
    fcntl(s, F_SETFL, O_NONBLOCK);
int flags = fcntl(s, F_GETFD);
if ((flags & O_NONBLOCK) == O_NONBLOCK) {
  fprintf(stderr, "nonblocking active");
}
else {
  fprintf(stderr, "nonblocking not active");
}
    //End check

fd_set fds;
int n;
struct timeval tv;
// set up the file descriptor set
FD_ZERO(&fds);
FD_SET(s, &fds);
// set up the struct timeval for the timeout
tv.tv_sec = timeout;
tv.tv_usec = 0;
// wait until timeout or data received
n = select(s+1, &fds, NULL, NULL, &tv);
if (n == 0){
    return -2; // timeout!
}
if (n == -1){
    return -1; // error
}
// data must be here, so do a normal recv()
return recv(s, buf, len, 0);
    }

所以,我添加了一段代码,告诉我NONBLOCK是否已设置,但从未读过非阻塞活动,所以在我的代码中,非阻塞不活动。 如何修改我的代码才能启用它?

问题是当我从客户端读取字符串并且有这样的代码时:

        char headerstring[512];
    memset(headerstring,0,512);
    if(this->recvtimeout(client_fd,headerstring,sizeof(headerstring),10) < 0){
        close(client_fd);
    }

一切正常,但是在事务期间关闭连接的flooder,服务器会关闭。 我尝试过try-catch和其他任何东西......但没有。

2 个答案:

答案 0 :(得分:1)

将套接字设置为非阻塞的正常方法是

  int x;
  x=fcntl(s,F_GETFL,0);
  fcntl(s,F_SETFL,x | O_NONBLOCK);

在您的代码中,您将使用

获取标记
int flags = fcntl(s, F_GETFD);

而你应该这样做

  x=fcntl(s,F_GETFL,0);

因此,实际上可以在套接字上启用非阻塞功能。

答案 1 :(得分:0)

有几件事:

  1. select()致电后:

    if(n < 0) continue;
    if(FD_ISSET(s, &fds)) { //check if Socket ready for reading
       FD_CLR(s, &fds);  // Clear for next time
       // call recv()
    }
    
  2. 将套接字设置为非阻塞,如下所示:

    /* set socket as non-blocking */
    int x = fcntl(s, F_GETFL, 0);
    fcntl(s, F_SETFL, x | O_NONBLOCK);