【发布时间】:2011-03-10 09:31:37
【问题描述】:
我在尝试将阻塞套接字服务器转换为非阻塞套接字服务器时遇到了一个奇怪的问题。虽然使用阻塞套接字发送消息时只收到一次,但使用非阻塞套接字时,消息似乎被接收了无数次。 这是更改的代码:
return ::write(client, message, size);
到
// 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;
编辑:主集的初始化如下所示:
// Private member variables in header file
fd_set master_set;
int sock;
...
// 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);
...
// 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);
}
我已经确认,在这两种情况下,代码只会针对违规消息调用一次。此外,客户端代码根本没有改变 - 有人有什么建议吗?
【问题讨论】:
-
请注意,非阻塞套接字返回 -1 并带有 errno==EWOULDBLOCK 或 errno==EAGAIN 而不是阻塞。
-
master_set 长什么样子?
-
您没有使用 fd_sets 或未正确选择,请仔细阅读它们......
-
在
strace下运行你的程序,你会看到真正发生了什么。 (另外,更改 return 0; 以返回 total_sent; ,以及给出的其他建议)