c - 在 C 中设置 select() 和 write_fds

标签 c sockets select

我一定是在设置 select()write_fds 时做错了什么。目前,当我第一次调用 sendData() 时,它会从缓冲区发送 117 个字节(全部)。然后立即再次调用它,即使缓冲区中没有更多数据要发送,它也会一直调用 sendData()

知道我在这里做错了什么吗?

int readData(int j){
    return recv(j, buf , nbytes , 0);
}   
int sendData(int j){
    unsigned v = fcntl(j, F_GETFL, 0);
    fcntl(j, F_SETFL, v | O_NONBLOCK);

    return send(j, buf, nbytes, 0);
}   

fd_set master;   
fd_set read_fds; 
fd_set write_fds;   
int fdmax;       
...
FD_ZERO(&master);   
FD_SET(socket, &master);
fdmax = socket;

for(;;){
    FD_ZERO(&read_fds);
    FD_ZERO(&write_fds);

    read_fds = master; 
    write_fds = master;
    if(select(fdmax+1, &read_fds, &write_fds, NULL, NULL) == -1){
        exit(4);
    }   
    for(i = 0; i <= fdmax; i++){
        if(FD_ISSET(i, &read_fds)){
            if(i == socket){
                // handle new connections
                addrlen = sizeof remoteaddr;
                newfd = accept(socket, (struct sockaddr *)&addr, &addrlen);
                FD_SET(newfd, &master);
                if(newfd > fdmax) fdmax = newfd;
            }else{  
                // we got some data from a client
                readData(i); 
            }   
        } else if(FD_ISSET(i, &write_fds)){
            if(i != socket){
                // send data when notified
                sendData(i);
            }
        }    
    }   
}

最佳答案

您要求 select 在网络堆栈中有空间发送更多数据时通知您(这就是 write_fds 正在检查的内容)。因为你只写了 117 个字节,所以有足够的空间,所以它立即返回,告诉你写更多的数据。

由于您没有更多数据要发送,您要做的是从 write_fds 集中删除该文件描述符。如果对 send 的调用返回短写(无法写入所有数据)或 EWOULDBLOCK(假设您将其设置为非-阻塞模式)。

这给您的代码带来了主要问题——您在调用 send/recv 时没有检查返回值,因此您不知道实际发送或接收了多少数据。

关于c - 在 C 中设置 select() 和 write_fds,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36415680/

相关文章:

sql - 根据单个值排除整个组

MySQL SELECT 从表中的多列

c - 取malloc()、realloc()和free()的地址是否可移植?

c - 从标准输入读取字符串长度

c++ - 哪里可以找到这个函数的源代码?

java - 使用本地主机上的套接字发送消息

php - MySQL 使用 EXISTS 选择计数

c - 将 CPU 亲和性设置为进程 - C - Linux

c++ - 如何使用 recvfrom 获取 AF_INET6 套接字的地址

c - 建立多个连接时如何在C中设置套接字超时?