Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在C+中使用recv或read函数从tcp套接字读取大请求+;?_C++_Sockets_Tcp - Fatal编程技术网

C++ 如何在C+中使用recv或read函数从tcp套接字读取大请求+;?

C++ 如何在C+中使用recv或read函数从tcp套接字读取大请求+;?,c++,sockets,tcp,C++,Sockets,Tcp,我正在开发一个服务器,它将接收http请求。所有这些都可以正常工作,但是当请求很大时,例如30MB,就会丢失该请求的一部分。换句话说,当收到大请求时,服务器无法读取所有数据 以下是我的tcp服务器的代码: TcpServer.h: #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #如果已定义(_WIN32)| |已定义(_WIN64) #包括 #包括 类型定义插座; typedef int msg_size_t; #定义WSA_LAST_ERR WSAGetLas

我正在开发一个服务器,它将接收http请求。所有这些都可以正常工作,但是当请求很大时,例如30MB,就会丢失该请求的一部分。换句话说,当收到大请求时,服务器无法读取所有数据

以下是我的tcp服务器的代码:

TcpServer.h

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#如果已定义(_WIN32)| |已定义(_WIN64)
#包括
#包括
类型定义插座;
typedef int msg_size_t;
#定义WSA_LAST_ERR WSAGetLastError()
#定义SOCKET\u SEND SD\u SEND
#定义SOCKET\u RECEIVE SD\u RECEIVE
#pragma注释(lib,“Ws2_32.lib”)
#elif已定义(uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
#包括
#包括
#包括
typedef int socket\u t;
typedef ssize\u t msg\u size\t;
#定义无效的\u套接字(套接字\u t)(-1)
#定义套接字错误(-1)
#定义套接字发送关闭
#定义套接字接收关闭
#定义WSA_LAST_ERR ERR no
#否则
#此平台不支持错误库
#恩迪夫
#定义默认_主机“127.0.0.1”
#定义默认的\u端口8000
#定义最大BUFF大小8192*8-1
typedef std::函数tcpHandler;
类TcpServer
{
私人:
uint16_t_端口;
常量字符*主机;
tcpHandler\u处理器;
插座(t)插座;;
sockaddr_in_SocketAddress{};
void startListener();
无效serveConnection(const套接字和客户端);
静态int闭合插座(常数插座和插座);
静态空洞wsaCleanUp();
空洞清理(常数插座和连接);
标准::字符串记录(常量套接字和连接);
int init();
枚举读取结果
{
继续,没有
};
ReadResult\u handleError(字符*缓冲区、int和status);
公众:
结构上下文
{
const char*host=nullptr;
uint16_t端口=0;
tcpHandler=nullptr;
};
显式TcpServer(TcpServer::Context ctx);
void listendserve();
静态无效发送(常量字符*数据、常量套接字和连接);
静态无效写入(常量字符*数据、大小字节、常量套接字和连接);
~TcpServer();
};
TcpServer.cpp

#包括“tcp_server.h”
bool set\u socket\u阻塞(int-fd,bool阻塞)
{
如果(fd<0)
{
返回false;
}
#如果已定义(_WIN32)| |已定义(_WIN64)
无符号长模式=阻塞?0:1;
返回ioctlsocket(fd、FIONBIO和mode)==0;
#否则
int flags=fcntl(fd,F_GETFL,0);
如果(标志==-1)
{
返回false;
}
标志=阻塞?(标志和非阻塞):(标志非阻塞);
返回fcntl(fd,F_SETFL,flags)==0;
#恩迪夫
}
TcpServer::TcpServer(TcpServer::Context ctx)
{
if(ctx.host==nullptr)
{
ctx.host=默认\u主机;
}
如果(ctx.port==0)
{
ctx.port=默认_端口;
}
this->_host=ctx.host;
此->\u端口=ctx.port;
if(ctx.handler==nullptr)
{
抛出std::无效的_参数(“Context::handler不能为null”);
}
this->_handler=ctx.handler;
如果(ctx.logger==nullptr)
{
ctx.logger=logger::getInstance();
}
这个->\u socketAddr={};
这个->\u套接字={};
}
TcpServer::~TcpServer()
{
TcpServer::cleanUp(这个->\u套接字);
}
int TcpServer::init()
{
此->\u socketAddr.sin\u family=AF\u INET;
此->\u socketAddr.sin\u端口=htons(此->\u端口);
此->\u socketAddr.sin\u addr.s\u addr=inet\u addr(此->\u主机);
memset(此->\u socketAddr.sin\u zero、\0',此->\u socketAddr.sin\u zero的大小);
此->\u socket=socket(PF\u INET、SOCK\u STREAM、IPPROTO\u TCP);
if(this->\u socket==无效的\u socket)
{
std::cout(u port)\u socket,(sockaddr*)和this->\u socketAddr,sizeof(this->\u socketAddr))==socket\u错误)
{
std::cout(端口)\U插座);
返回套接字错误;
}
if(侦听(此->\u套接字,SOMAXCONN)=套接字\u错误)
{
std::cout _port)init()!=0)
{
返回;
}
#如果已定义(_WIN32)| |已定义(_WIN64)
智力状态;
WSADATA WSADATA;
状态=WSAStartup(MAKEWORD(2,2)和wsaData);
如果(状态!=0)
{
标准::cout_socketAddr);
socket\u t connection=accept(这个->\u socket,(sockaddr*)和这个->\u socketAddr,&connectionLen);
if(连接!=无效的_套接字)
{
设置插座阻塞(连接,错误);
std::thread newThread(&TcpServer::serveConnection,this,connection);
newThread.detach();
}
其他的
{

std::cout在请求完成之前,您需要一直调用
recv
。TCP无法告诉您请求何时完成-这不是它所做的(它可以告诉您连接何时关闭,但这会关闭连接)。因此,您需要另一种方法来知道何时停止读取

目前,只要20毫秒内没有任何数据,您就停止读取。这不是很可靠。网络中断可能会导致20毫秒延迟,然后您会过早停止读取


在HTTP中,客户端通过使用Content-Length标头告诉您请求正文的长度。请求由请求标头和请求正文组成,因此服务器需要读取标头(在一个空行后停止),然后查看标头以查看请求正文的长度,然后读取正文(在该字节数之后停止)。

套接字始终读取(我不建议对30+MD消息使用
MSG_WAITALL
)在读取请求的最大值之前,请提供可用的数据。没有超时是绝对安全的,因为数据包可能已通过Outer Nowhere重新路由,并且在相当长的一段时间内无法到达您。相反,请循环读取,直到您获得所需的所有数据或连接出现无法恢复的故障。1.TCP/IP没有消息边界。我可能会发送wo消息,每个40字节,你会收到一条80字节的消息,或者我发送一条30Mb的消息,你会收到1000字节的消息