所以我正在建立一个聊天服务器,现在我试图回应来自客户端的所有消息。目前,只要收到消息,我就会在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);
}
}
}
}
的两次调用似乎多余。
{{1}}
答案 0 :(得分:0)
我不建议直接在sendData()
内调用readData()
。它们应该分开。让readData()
将接收到的数据返回给调用者,让调用者决定如何处理它。如果呼叫者想要发送数据,则可以根据需要调用sendData()
。
要解决select()
问题,您需要为传出数据创建每个套接字缓冲区。并确保套接字以非阻塞模式运行。
如果缓冲区为空时调用sendData()
,则send()
尽可能多地调用调用者的数据。 send()
将返回它实际接受的字节数。如果send()
报告EWOULDBLOCK
或EAGAIN
错误,请停止发送并将任何未发送的数据附加到缓冲区的末尾。
如果缓冲区不为空时调用sendData()
,只需将新数据附加到缓冲区的末尾,然后退出而不调用send()
。
每当select()
报告套接字是可写的,send()
当前缓存在该套接字缓冲区中的任何内容(如果有的话)。对于每个成功的send()
,从缓冲区前面删除报告的字节数。如果缓冲区耗尽或send()
失败,则停止发送。