我希望发送一条大信息> 1 MB通过windows套接字发送api。有没有一种有效的方法,我不想循环,然后以块的形式发送数据。我在某处读过你可以增加套接字缓冲区的大小,这可能有所帮助。任何人都可以详细说明这一点。任何帮助表示赞赏
答案 0 :(得分:3)
你应该,并且实际上必须循环以块的形式发送数据。
正如Beej网络指南中所解释的那样:
“send()返回实际发送的字节数 - 这可能小于你告诉它发送的数量!看,有时候你告诉它发送一大堆数据而它无法处理它它会发射尽可能多的数据,并相信你以后会发送其余数据。“
这意味着即使您将数据包大小设置为1MB,send()函数也可能不会发送所有数据包,并且您必须循环,直到您的send()调用发送的总字节数总计为您尝试发送的字节数。实际上,数据包的大小越大,send()就越不会发送它。
除此之外,您不希望发送1MB数据包,因为如果它们丢失,您将不得不再次传输整个1MB数据包,而如果您丢失了1K数据包,则重传它并不是什么大问题。
总之,你必须循环你的send()调用,接收者甚至必须循环他们的recv()调用。您可能需要在每个数据包前加一个小标头,告诉接收器正在发送多少字节,以便接收器可以循环适当的次数。
我建议您查看Beej的网络指南,了解有关send()和recv()以及如何处理此问题的更多详细信息。它可以在http://beej.us/guide/bgnet/output/print/bgnet_USLetter.pdf
找到答案 1 :(得分:1)
为什么不想以块的形式发送它?
这是在99%的情况下这样做的方法。
答案 2 :(得分:1)
是什么让你认为发送块是低效的?无论如何,操作系统可能会大量发送“发送”电话,并且可能会合并小电话。
同样在接收方,客户端应该循环,因为无法保证一次性获取所有数据。
答案 3 :(得分:0)
Windows套接字子系统无需发送您提供的整个缓冲区。您无法强制使用它,因为某些网络级协议的数据包大小有上限。
答案 4 :(得分:0)
实际上,您实际上可以使用Winsock分配一个大缓冲区并发送一个调用。如果你没有搞乱套接字缓冲区大小,缓冲区通常会被复制到内核模式以便发送。
理论上有可能它会在没有发送所有内容的情况下返回,所以你真的应该循环以获得正确性。但是,您发送的块应该很大(64k或球场)以避免重复的内核转换。
答案 5 :(得分:0)
如果你想做一个循环,你可以使用这个C ++代码:
#define DEFAULT_BUFLEN 1452
int SendStr(const SOCKET &ConnectSocket, const std::string &str, int strlen){
char sndbuf[DEFAULT_BUFLEN];
int sndbuflen = DEFAULT_BUFLEN;
int iResult;
int count = 0;
int len;
while(count < strlen){
len = min(strlen-count, sndbuflen);
//void * memcpy ( void * destination, const void * source, size_t num );
memcpy(sndbuf,str.data()+count,len);
// Send a buffer
iResult = send(ConnectSocket, sndbuf, len, 0);
// iResult: Bytes sent
if (iResult == SOCKET_ERROR){
throw WSAGetLastError();
}
else{
if(iResult > 0){
count+=iResult;
}
else{
break;
}
}
}
return count;
}