在C中使用select()和write_fds时发送数据的正确方法

问题描述 投票:0回答:1

所以我正在构建一个聊天服务器,现在我正在尝试回显来自客户端的所有消息。目前,我一收到消息,就会在

readData()
内发回。然而,一旦我发送,
select()
就会通知
write_fds
并且
sendData()
会被呼叫,即使我已经打电话给
send()

我发送数据的大部分调用都在

readData()
内。

  • 这是使用
    select()
    write_fds
    的正确方法吗?
  • 如何通知
    select()
    我想要发送数据而不需要两次调用
    send()

对我来说,必须处理两个

send()
电话似乎是多余的。

int readData(int j){
    // get message from the client
    recv(j, client_buffer , 6000 , 0);
    // echo message to the client
    send(j, client_buffer, strlen(client_buffer));
}   
int sendData(int j){
    send(j, buf, nbytes, 0);
}   

for(;;){
    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 == listener){
                // handle new connections
                addrlen = sizeof remoteaddr;
                newfd = accept(listener, (struct sockaddr *)&addr, &addrlen);
                FD_SET(newfd, &master);
                if(newfd > fdmax) fdmax = newfd;
            }else{  
                // we got some data from a client
                readData(i); 
            }   
        }  
        if(FD_ISSET(i, &write_fds)){
            if(i != listener){
                // send data when notified
                sendData(i);
            }
        }    
    }   
}
c sockets posix-select
1个回答
0
投票

我不建议直接在

sendData()
内部致电
readData()
。它们应该分开存放。让
readData()
将接收到的数据返回给调用者,并让调用者决定如何处理它。如果调用者想要发送数据,则可以根据需要调用
sendData()

要解决

select()
问题,您需要为传出数据创建每个套接字缓冲区。并确保套接字以非阻塞模式运行。

  1. 如果在缓冲区为空时调用

    sendData()
    ,则
    send()
    尽可能多地调用者的数据。
    send()
    将返回它实际接受的字节数。如果
    send()
    报告
    EWOULDBLOCK
    EAGAIN
    错误,请停止发送并将所有未发送的数据附加到缓冲区末尾。

  2. 如果在缓冲区不为空时调用

    sendData()
    ,只需将新数据追加到缓冲区末尾并退出,根本不调用
    send()

每当

select()
报告套接字可写时,
send()
当前缓存在该套接字缓冲区中的任何内容(如果有)。对于每个成功的
send()
,从缓冲区前面删除报告的字节数。如果缓冲区耗尽或
send()
失败,请停止发送。

© www.soinside.com 2019 - 2024. All rights reserved.