Winsock 接收到的字节数无效
Winsock invalid received byte number
我目前在尝试验证接收到的字节数时遇到 Winsock
相关问题。
在我的应用程序中,我使用非阻塞套接字来抛出我自己的 Timeout
异常。这里是 Winsock
:
初始化的相应代码
// Initialize Winsock
WSAData winSockData;
WORD dllVersion = MAKEWORD(2, 1);
long iResult = WSAStartup(dllVersion, &winSockData);
if (iResult != NO_ERROR)
return;
addrinfo* serverAddress = nullptr;
addrinfo* ptr = nullptr, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
iResult = getaddrinfo("127.0.0.1", "10011", &hints, &serverAddress);
if (iResult != 0)
return;
// Create communication socket
SOCKET connectSocket = socket(AF_INET, SOCK_STREAM, /*IPPROTO_TCP*/0);
if (connectSocket == INVALID_SOCKET)
return;
// Establish connection to server
iResult = connect(connectSocket, serverAddress->ai_addr, (int)serverAddress->ai_addrlen);
if (iResult == SOCKET_ERROR)
return;
// Set socket to non-blocking
ULONG mode = 1;
m_iResult = ioctlsocket(m_connectSocket, FIONBIO, &mode);
if (m_iResult == SOCKET_ERROR)
return;
// server address info not needed anymore
freeaddrinfo(serverAddress);
应用程序首先连接到给定的 telnet 服务器,发送请求,然后等待相应的响应消息。
传入数据存储在适当的字符数组中,称为 m_serverMsg
(固定大小 BUFSIZE
,当前设置为 4200 字节)。
如果检索服务器响应消息花费的时间过长(存储在 g_requestTimeout
中的最大允许时间),我自己的 TimeoutException
会被抛出。
如果在消息缓冲区中找到换行符 (\r\n
),则给定的服务器消息已结束。
但是,以下用于检索服务器响应消息的部分未按预期工作。预期的传入数据字节为 1,040
,但实际字节始终为 3,435,973,836
。
unsigned long long startTime = getWallTimeInMs();
bool retry = true;
unsigned int receivedBytes = 0;
// Fetch server response
do
{
try
{
m_iResult = fetchMessage(m_connectSocket, m_serverMsg, int(BUFSIZE - receivedBytes));
if (m_iResult == SOCKET_ERROR)
throw std::exception();
if (m_iResult > 0)
{
for (unsigned int i = receivedBytes; i < receivedBytes + m_iResult; i++)
{
char* eol = strstr(m_serverMsg, "\r\n");
if (eol)
{
retry = false;
break;
}
}
receivedBytes += m_iResult;
}
}
catch (CommException e)
{
// in case there's a short delay in retrieving the server response message
if (getWallTimeInMs() - startTime < g_requestTimeout)
Sleep(20);
else
// response timeout exceeded; connection has been lost
throw CommException("server not responding in time.", CommProblem::ConnectionLost);
}
catch (std::exception& e)
{
std::cout << "There was a socket related problem." << std::endl;
std::cout << "Error code: " << WSAGetLastError() << std::endl;
}
} while (retry);
这就是函数 fetchMessage()
的样子:
int CommCenter::fetchMessage(SOCKET socket, char* buffer, int bufSize, int flags)
{
int result = recv(socket, buffer, bufSize, flags);
// if operation couldn't be executed (e.g. because server is down),
// throw according exception
if (result == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
throw CommException("delay in connection.", CommProblem::Delay);
else throw;
}
return result;
}
这部分
for (unsigned int i = receivedBytes; i < receivedBytes + m_iResult; i++)
{
if (m_serverMsg[i] == '\r\n')
{
retry = false;
break;
}
}
不对,'\r\n'
和"\r\n"
不一样,不能这样比较。
要更正它,请使用 strstr
这样的函数
char* eol = strstr(m_serverMsg, "\r\n");
if(eol != NULL)
{
retry = false;
break;
}
或将m_serverMsg
转换为std::string
并使用find
方法
if(std::string(m_serverMsg, receivedBytes, m_iResult).find("\r\n") != std::string::npos)
{
retry = false;
break;
}
我目前在尝试验证接收到的字节数时遇到 Winsock
相关问题。
在我的应用程序中,我使用非阻塞套接字来抛出我自己的 Timeout
异常。这里是 Winsock
:
// Initialize Winsock
WSAData winSockData;
WORD dllVersion = MAKEWORD(2, 1);
long iResult = WSAStartup(dllVersion, &winSockData);
if (iResult != NO_ERROR)
return;
addrinfo* serverAddress = nullptr;
addrinfo* ptr = nullptr, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
iResult = getaddrinfo("127.0.0.1", "10011", &hints, &serverAddress);
if (iResult != 0)
return;
// Create communication socket
SOCKET connectSocket = socket(AF_INET, SOCK_STREAM, /*IPPROTO_TCP*/0);
if (connectSocket == INVALID_SOCKET)
return;
// Establish connection to server
iResult = connect(connectSocket, serverAddress->ai_addr, (int)serverAddress->ai_addrlen);
if (iResult == SOCKET_ERROR)
return;
// Set socket to non-blocking
ULONG mode = 1;
m_iResult = ioctlsocket(m_connectSocket, FIONBIO, &mode);
if (m_iResult == SOCKET_ERROR)
return;
// server address info not needed anymore
freeaddrinfo(serverAddress);
应用程序首先连接到给定的 telnet 服务器,发送请求,然后等待相应的响应消息。
传入数据存储在适当的字符数组中,称为 m_serverMsg
(固定大小 BUFSIZE
,当前设置为 4200 字节)。
如果检索服务器响应消息花费的时间过长(存储在 g_requestTimeout
中的最大允许时间),我自己的 TimeoutException
会被抛出。
如果在消息缓冲区中找到换行符 (\r\n
),则给定的服务器消息已结束。
但是,以下用于检索服务器响应消息的部分未按预期工作。预期的传入数据字节为 1,040
,但实际字节始终为 3,435,973,836
。
unsigned long long startTime = getWallTimeInMs();
bool retry = true;
unsigned int receivedBytes = 0;
// Fetch server response
do
{
try
{
m_iResult = fetchMessage(m_connectSocket, m_serverMsg, int(BUFSIZE - receivedBytes));
if (m_iResult == SOCKET_ERROR)
throw std::exception();
if (m_iResult > 0)
{
for (unsigned int i = receivedBytes; i < receivedBytes + m_iResult; i++)
{
char* eol = strstr(m_serverMsg, "\r\n");
if (eol)
{
retry = false;
break;
}
}
receivedBytes += m_iResult;
}
}
catch (CommException e)
{
// in case there's a short delay in retrieving the server response message
if (getWallTimeInMs() - startTime < g_requestTimeout)
Sleep(20);
else
// response timeout exceeded; connection has been lost
throw CommException("server not responding in time.", CommProblem::ConnectionLost);
}
catch (std::exception& e)
{
std::cout << "There was a socket related problem." << std::endl;
std::cout << "Error code: " << WSAGetLastError() << std::endl;
}
} while (retry);
这就是函数 fetchMessage()
的样子:
int CommCenter::fetchMessage(SOCKET socket, char* buffer, int bufSize, int flags)
{
int result = recv(socket, buffer, bufSize, flags);
// if operation couldn't be executed (e.g. because server is down),
// throw according exception
if (result == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
throw CommException("delay in connection.", CommProblem::Delay);
else throw;
}
return result;
}
这部分
for (unsigned int i = receivedBytes; i < receivedBytes + m_iResult; i++)
{
if (m_serverMsg[i] == '\r\n')
{
retry = false;
break;
}
}
不对,'\r\n'
和"\r\n"
不一样,不能这样比较。
要更正它,请使用 strstr
这样的函数
char* eol = strstr(m_serverMsg, "\r\n");
if(eol != NULL)
{
retry = false;
break;
}
或将m_serverMsg
转换为std::string
并使用find
方法
if(std::string(m_serverMsg, receivedBytes, m_iResult).find("\r\n") != std::string::npos)
{
retry = false;
break;
}