非块TCP套接字编程

non-block TCP socket programming

本文关键字:编程 套接字 TCP 非块      更新时间:2023-10-16

我想让非阻塞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;

}

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

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

如果你要进行非阻塞套接字编程,你必须明白,当没有什么可读时,read()将返回-1,errno设置为EAGAIN/EWOULDBLOCK,并使用select()告诉你什么时候不会。

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

在您的情况下,我认为没有必要使用非阻塞服务器。如果你真的是这个意思,你应该看看select()epoll和类似的。至于你的代码,有几个问题:

  1. 服务器端的accept()应该在while循环中
  2. accept()在成功时返回已接受套接字的描述符,该描述符应传递给read()
  3. 正如Prabhu的回答所说,您已经将套接字设置为O_NONBLOCK,因此accept()将立即返回。如果不存在要接受的连接,则errno将被设置为EAGAINEWOULDBLOCK

修改后的代码:

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;
    }
}