非块TCP套接字编程

时间:2014-04-25 06:36:34

标签: c++ sockets tcp nonblocking

我想制作非块TCP接收器,以便cilent可以定期向服务器发送消息(即每10分钟更新一次信息)。

我在本地机器上测试它。 'return_status'值表示'bind,accept,connect和write'正常工作,但read总是返回-1。有人可以解释一下吗?感谢

客户端代码。

#define CONTROLPORT 6000

int main(void)
{

int control_sock, return_status;
struct sockaddr_in control_addr;
socklen_t control_len;
memset(&control_addr, 0, sizeof(control_addr));
char control_message[10];

control_sock = socket(AF_INET, SOCK_STREAM, 0);

control_addr.sin_family = AF_INET;
control_addr.sin_addr.s_addr = inet_addr("192.168.16.133");
control_addr.sin_port = htons(CONTROLPORT);

return_status = bind(control_sock, (struct sockaddr *) &control_addr, sizeof(control_addr));

fcntl(control_sock, F_SETFL, O_NONBLOCK); 

return_status = listen(control_sock, 1);
    cout << return_status << endl;
return_status = accept(control_sock, (struct sockaddr *) &control_addr, &control_len); 
    cout << return_status << endl;

while(1){

    return_status = read(control_sock,control_message,sizeof(control_message));

    cout << return_status << endl;

}







}

发件人方代码

#define CONTROLPORT 6000

using namespace std;

int main(void)
{

int control_sock, return_status;
struct sockaddr_in control_addr;
socklen_t control_len;
memset(&control_addr, 0, sizeof(control_addr));
char control_message[10];
control_message[10] = 111;

control_sock = socket(AF_INET, SOCK_STREAM, 0);

control_addr.sin_family = AF_INET;
control_addr.sin_addr.s_addr = inet_addr("192.168.16.133");
control_addr.sin_port = htons(CONTROLPORT);

return_status = connect(control_sock, (struct sockaddr *) &control_addr, sizeof(control_addr));
    cout << return_status << endl;



    return_status = write(control_sock,control_message,sizeof(control_message));

    cout << return_status << endl;

}

3 个答案:

答案 0 :(得分:0)

您已将套接字设置为非阻塞,因此accept在某个连接之前不会阻塞。 accept将返回EAGAIN或EQOULDBLOCK。检查错误。如果没有此检查,您的代码将继续执行read。它返回-1(再次检查errno),因为首先没有建立连接。

您必须使用selectpollepoll来查看非阻塞套接字上的事件。这是为了弄清楚是否有人在已建立的连接上连接/发送数据。

答案 1 :(得分:0)

在您的情况下,我不认为非阻塞服务器是必要的。如果您的确是这个意思,那么您应该看一下select()epoll和类似内容。至于你的代码,还有几个问题:

    服务器端的
  1. accept()应该在while循环中。
  2. accept()成功返回已接受套接字的描述符,此描述符应传递给read()
  3. 正如Prabhu的回答所说,您已将套接字设置为O_NONBLOCK,因此accept()会立即返回。如果不接受任何联系,则errno将设置为EAGAINEWOULDBLOCK
  4. 修改后的代码:

    int main(void)
    {
        int control_sock, return_status;
        struct sockaddr_in control_addr;
        socklen_t control_len;
        memset(&control_addr, 0, sizeof(control_addr));
        char control_message[10];
    
        control_sock = socket(AF_INET, SOCK_STREAM, 0);
    
        control_addr.sin_family = AF_INET;
        control_addr.sin_addr.s_addr = inet_addr("192.168.7.134");
        control_addr.sin_port = htons(CONTROLPORT);
    
        return_status = bind(control_sock, (struct sockaddr *) &control_addr, sizeof(control_addr));
    
        //fcntl(control_sock, F_SETFL, O_NONBLOCK);
    
        return_status = listen(control_sock, 1);
        cout << return_status << endl;
        while(1){
            return_status = accept(control_sock, (struct sockaddr *) &control_addr, &control_len);
            cout << return_status << endl;
    
    
            return_status = read(return_status,control_message,sizeof(control_message));
    
            cout << return_status << endl;
    
        }
    }
    

答案 2 :(得分:0)

如果您打算进行非阻塞套接字编程,您必须了解read()将返回-1,当没有任何内容要读取时,errno设置为EAGAIN / EWOULDBLOCK,并使用select()告诉你什么时候不会。

NB 4是Unix,Solaris,HP-UX,AIDA,Linux等中的有效套接字FD ...