嘗試將阻塞套接字服務器轉換爲非阻塞套接字服務器時出現奇怪問題。雖然這個消息只有在使用阻塞套接字發送時纔會被接收,但是使用非阻塞套接字的消息似乎會被無數次接收。 這裏是已更改代碼:在C++中正確寫入非阻塞套接字
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代替的阻塞。 – ninjalj 2010-06-30 22:50:26
master_set是什麼樣的? – Mau 2010-06-30 23:04:08
你沒有使用fd_sets或正確選擇,閱讀它們...... – SoapBox 2010-06-30 23:27:22