我在客户端使用 blocking FSocket 连接到tcp服务器,如果没有来自服务器的消息,套接字线程将在函数 FScoket::Recv() 中阻塞,如果TCP服务器关闭,套接字线程仍然在此函数中阻塞 . 但是当使用 BSD Socket API 的阻塞套接字时,线程将从 recv 函数传递并在TCP服务器关闭时返回 errno ,那么它是否是FSocket的缺陷?
uint32 HRecvThread::Run()
{
uint8* recv_buf = new uint8[RECV_BUF_SIZE];
uint8* const recv_buf_head = recv_buf;
int readLenSeq = 0;
while (Started)
{
//if (TcpClient->Connected() && ClientSocket->GetConnectionState() != SCS_Connected)
//{
// // server disconnected
// TcpClient->SetConnected(false);
// break;
//}
int32 bytesRead = 0;
//because use blocking socket, so thread would block in Recv function if have no message
ClientSocket->Recv(recv_buf, readLenSeq, bytesRead);
.....
//some logic of resolution for tcp msg bytes
.....
}
delete[] recv_buf;
return 0
}
2 回答
正如我所料,您忽略了返回代码,这可能表示成功或失败,因此您在错误或流结束条件下无限循环(不阻塞) .
注意您应该在堆栈上分配
recv_buf
,而不是动态分配 . 唐't use the heap when you don'吨必须 .在UE4 C编程部分的论坛上有类似的问题 . 以下是讨论:
https://forums.unrealengine.com/showthread.php?111552-Recv-function-would-keep-blocking-when-TCP-server-shutdown
长话短说,在UE4 Source中,他们将EWOULDBLOCK视为错误 . 代码注释表明它们不将其视为错误 .
此外,在打开端口和轮询端口时应该使用几个辅助函数(我假设您正在轮询,因为您正在使用阻塞调用)
FSocket::Connect
返回一个bool,所以一定要检查返回值 .如果套接字发生错误,
FSocket::GetLastError
将返回UE4 Translated错误代码 .FSocket::HasPendingData
将返回一个值,通知您是否可以安全地从套接字读取 .FSocket::HasPendingConnection
可以查看您的连接状态 .FSocket::GetConnectionState
会告诉您活动的连接状态 .在调用
FSocket::Recv
之前使用这些辅助函数进行错误检查将帮助您在尝试读取数据之前确保处于良好状态 . 此外,在论坛帖子中指出,使用非阻塞代码按预期工作 . 因此,如果您没有特定的理由使用阻止代码,只需使用非阻塞实现 .此外,作为最后的提示,使用
FSocket::Wait
将阻塞,直到您的套接字处于您选择的超时状态,即可读或具有数据 .