我有以下功能设置,每2分钟从服务器接收数据.我第一次调用函数它似乎工作,但然后它冻结在recv永远不会返回的调用.我是否需要在每次调用时分配缓冲区,即使服务器没有任何内容可以发送?
#define RCVBUFSIZE 32
void Receive()
{
UINT totalBytesRcvd = 0, bytesRcvd = 0;
char buffer[RCVBUFSIZE]; /* Buffer for string */
/* Receive up to the buffer size (minus 1 to leave space for
a null terminator) bytes from the sender */
bytesRcvd = recv(sockClient, buffer, RCVBUFSIZE - 1, 0);
if (bytesRcvd)
{
buffer[bytesRcvd] = '\0';
MessageBox(0, buffer, 0, 0); //some way to display the received buffer
}
else if (bytesRcvd == SOCKET_ERROR)
{
return;
}
}
Run Code Online (Sandbox Code Playgroud)
(1)你的缓冲区没有真正分配,它驻留在堆栈上.您通常不必担心在堆栈上使用32个字节.
(2)recv应该阻止,直到它有东西要接收.你可以通过使用非阻塞套接字或使用来解决这个问题select.请参阅此处以供参考.
特别是,你可以
(2a)使用ioctlsocket将套接字设置为非阻塞模式.然后,当你打电话read,没有什么可读,你会得到错误EWOULDBLOCK.
unsigned long non_blocking = 1;
ioctlsocket (sockClient, FIONBIO, &non_blocking);
Run Code Online (Sandbox Code Playgroud)
然后读书变成了
bytesRcvd = recv(sockClient, buffer, RCVBUFSIZE - 1, 0);
if (bytesRcvd == -1) {
if (WSAGetLastError() == EWOULDBLOCK) {
// nothing to read now
} else {
// an actual error occurred
}
} else {
// reading was successful. Call to MsgBox here
}
Run Code Online (Sandbox Code Playgroud)
(2b)或者,您可以在实际调用之前调用select以确定是否有要读取的数据read.
struct timeval timeout;
timeout.tv_usec = 0;
timeout.tv_sec = 0;
fd_set r;
FD_ZERO (&r);
FD_SET (sockClient, &r);
switch (select (sockClient + 1, &r, NULL, NULL, &timeout)) {
case -1:
// error
break;
case 0:
// nothing to read
break;
case 1:
// you may call read ()
break;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
285 次 |
| 最近记录: |