![](/img/trans.png)
[英]Recv() Function Hangs After Sending HTTP GET Request in Winsock in C++
[英]C++ multithread HTTP Server - recv() hangs up after first sending first response
I'm trying to build a multithread HTTP server using C++ and winsock2.h and sys/socket.h.However, after sending response successfully to first request, accept() function captures other requests and sends through thread pool but those threads hangs up在 recv() function 所以 function 永远无法从套接字捕获数据。这是我的代码。
void HTTPServer::init()
{
#ifdef _WIN32
WSADATA wsaData;
WSAStartup(0x202,&wsaData);
if((mSock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == INVALID_SOCKET)
#else
if((mSock = socket(AF_INET,SOCK_STREAM,0)) < 0)
#endif
{
std::cout << "Error while initilazing socket\n";
}
mServerAddr.sin_family = AF_INET;
mServerAddr.sin_port = htons(mPort);
#ifdef _WIN32
mServerAddr.sin_addr.S_un.S_addr = INADDR_ANY;
#else
mServerAddr.sin_addr.S_addr = INADDR_ANY;
#endif
if(bind(mSock, (struct sockaddr*) &mServerAddr, sizeof(mServerAddr)) < 0)
{
std::cout << "Error while binding socket\n";
}
if(listen(mSock, SOMAXCONN))
{
std::cout << "Error while listening socket\n";
}
}
void HTTPServer::fRun()
{
ThreadPool* tPool = new ThreadPool(10);
while(1)
{
int size = sizeof(mClientAddr);
#ifdef _WIN32
if((mAcceptSocket = accept(mSock,(struct sockaddr*) &mClientAddr,&size)) == INVALID_SOCKET)
#else
if((mAcceptSocket = accept(mSock,(struct sockaddr*) &mClientAddr,&size))) < 0)
#endif
{
std::cout << "Error while initilazing accept socket\n";
}
std::cout << "Socket Sent " << mAcceptSocket << std::endl;
tPool->enqueue([&] { this->fOnRequest(mAcceptSocket); });
}
delete tPool;
}
void HTTPServer::fOnRequest(uint64_t socket)
{
const string reqData = fRecieveNext(mAcceptSocket);
const HTTPResponse res = fProcessRequest(reqData);
fSendResponse(res,socket);
std::cout << "Done";
}
const string HTTPServer::fRecieveNext(uint64_t socket)
{
int64_t recieveLength = 0,totalRecieved = 0;
int64_t recieveLengthBeforeBody = -1;
int contentLength = 0;
string rawData;
while(1)
{
memset(mBuffer,'\0',8192);
if((recieveLength = recv(socket,mBuffer,8192, 0)) == SOCKET_ERROR)
{
std::cout << "Error while receiving data from socket\n";
#ifdef _WIN32
std::cout << WSAGetLastError() << std::endl;
#endif
break;
}
if(recieveLength == 0)
break;
totalRecieved += recieveLength;
rawData += string(mBuffer,recieveLength);
if(totalRecieved > 32)
{
if(rawData.find("Content-Length") == string::npos && contentLength == 0)
break;
else
{
if(contentLength == 0)
{
auto pos = rawData.find("Content-Length:");
auto lengthStr = rawData.substr(pos + 16, rawData.find_first_of("\r",pos) - pos - 16);
contentLength = std::stoi(lengthStr);
}
if(rawData.find("\r\n\r\n") != string::npos && recieveLengthBeforeBody == -1)
{
recieveLengthBeforeBody = rawData.find("\r\n\r\n") + 4;
}
if(totalRecieved >= contentLength + recieveLengthBeforeBody)
break;
}
}
}
return rawData;
}
void HTTPServer::fSendResponse(const HTTPResponse& response,const uint64_t socket)
{
string resStr = response.fSerializeResponse();
size_t sent = 0,totalSent = 0;
char* buffer = &(resStr[0]);
while(totalSent < resStr.length())
{
if((sent = send(socket, buffer, resStr.length() - totalSent,0)) < 0)
{
std::cout << "Error while sending response" << std::endl;
}
buffer += sent;
totalSent += sent;
}
delete &response;
#ifdef _WIN32
if(shutdown(socket, SD_BOTH) == SOCKET_ERROR)
{
std::cout << "Error while closing socket" << std::endl;
std::cout << WSAGetLastError() << std::endl;
};
if(closesocket(socket) == SOCKET_ERROR)
{
std::cout << "Error while closing socket" << std::endl;
std::cout << WSAGetLastError() << std::endl;
};
#else
if(shutdown(socket, SHUT_RDWR) < 0)
{
std::cout << "Error while closing socket" << std::endl;
};
if(close(socket) < 0)
{
std::cout << "Error while closing socket" << std::endl;
};
#endif
}
看起来您希望在一次接收中收到一条 TCP 消息。 TCP 不能那样工作。 Tcp 是一个 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ 协议,发送给你的消息可以分成多个块。 TCP 只保证字节会以正确的顺序到达一次。
这会让你与输入不同步
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.