許多開發者以為 FD_WRITE 表示「可以發送數據」的通知,於是嘗試在收到該事件時調用 send()。實際上這會導致邏輯混亂甚至發送失敗。
FD_WRITE。send(),**無需等待 FD_WRITE**。send() 返回該錯誤,說明發送緩衝區滿,將數據暫存到應用層發送隊列,等待下一次 FD_WRITE 觸發後再嘗試發送隊列數據。send(),直到隊列空或再次 WSAEWOULDBLOCK。std::queue> sendQueue;
void OnSendRequest(const char* data, int len) {
sendQueue.emplace(data, data + len);
TrySend();
}
void TrySend() {
while (!sendQueue.empty()) {
auto& buf = sendQueue.front();
int ret = send(socket, buf.data(), buf.size(), 0);
if (ret > 0) {
if (ret == buf.size()) sendQueue.pop();
else { buf.erase(buf.begin(), buf.begin() + ret); }
} else if (WSAGetLastError() == WSAEWOULDBLOCK) {
break; // 等待 FD_WRITE
} else {
// 錯誤處理
break;
}
}
}
void OnEventSelect(WSAEVENT event) {
WSANETWORKEVENTS netEvents;
WSAEnumNetworkEvents(socket, event, &netEvents);
if (netEvents.lNetworkEvents & FD_WRITE) {
TrySend(); // 緩衝區可寫了,繼續發送隊列
}
// FD_READ, FD_CLOSE 等其他處理...
}
send(),遇阻塞入隊,FD_WRITE 來了再清隊。FD_WRITE,直接同步 send() 或用 select/poll/epoll/IOCP 更現代的模型。理解內核發送緩衝區機制,才能駕馭事件選擇模型,避免「想用 FD_WRITE 發數據卻只收到一次事件」的困境。