我在尝试将阻塞套接字服务器转换为非阻塞套接字时遇到了一个奇怪的问题。尽管使用阻塞套接字发送消息时只收到一次消息,但使用非阻塞套接字消息似乎可以无限次接收。这是更改的代码:
return ::write(client, message, size);
Run Code Online (Sandbox Code Playgroud)
到
// Nonblocking socket code
int total_sent = 0, result = -1;
while( total_sent < size ) {
// Create a temporary set of flags for use with the select function
fd_set working_set;
memcpy(&working_set, &master_set, sizeof(master_set));
// Check if data is available for the socket - wait 1 second for timeout
timeout.tv_sec = 1;
timeout.tv_usec = 0;
result = select(client + 1, NULL, &working_set, NULL, &timeout);
// We are able to write - do so
result = ::write(client, &message[total_sent], (size - total_sent));
if (result == -1) {
std::cerr << "An error has occured while writing to the server."
<< std::endl;
return result;
}
total_sent += result;
}
return 0;
Run Code Online (Sandbox Code Playgroud)
编辑:主集的初始化如下所示:
// Private member variables in header file
fd_set master_set;
int sock;
Run Code Online (Sandbox Code Playgroud)
...
// Creation of socket in class constructor
sock = ::socket(PF_INET, socket_type, 0);
// Makes the socket nonblocking
fcntl(sock,F_GETFL,0);
FD_ZERO(&master_set);
FD_SET(sock, &master_set);
Run Code Online (Sandbox Code Playgroud)
...
// And then when accept is called on the socket
result = ::accept(sock, NULL, NULL);
if (result > 0) {
// A connection was made with a client - change the master file
// descriptor to note that
FD_SET(result, &master_set);
}
Run Code Online (Sandbox Code Playgroud)
我已经确认,在这两种情况下,代码只为违规消息调用一次。此外,客户端代码根本没有改变 - 有没有人有任何建议?
fcntl(sock,F_GETFL,0);
Run Code Online (Sandbox Code Playgroud)
这如何使套接字非阻塞?
fcntl(sock, F_SETFL, O_NONBLOCK);
Run Code Online (Sandbox Code Playgroud)
此外,您不是在检查是否可以实际写入套接字非阻塞样式
FD_ISSET(client, &working_set);
Run Code Online (Sandbox Code Playgroud)