use*_*012 2 c c++ sockets winsock
我正在使用C++中的Winsock开发一个应用程序.我有一个200字节长的char数组,用于通过套接字发送字符串.
我的问题是当发送大于char数组的消息时,所以我决定以多个块发送它们,但我不知道该怎么做.
为了发送和接收数据,我使用常规send()和recv()功能:
recv(client, buffer, 200, NULL);
send(client, buffer, 200, NULL);
Run Code Online (Sandbox Code Playgroud)
更新
我有一个结构:
struct Pack
{
unsigned int senderId;
char str[200];
}
Run Code Online (Sandbox Code Playgroud)
在发送之前我转换struct为char数组.
Pack pk;
strcpy_s(pk.str, 200, "Some text to send.\0");
pk.senderId = 1 // user id
char *buffer = (char*)pk;
Run Code Online (Sandbox Code Playgroud)
如果字符串大小大于200则strcpy_s()崩溃.
你在Beej的网络编程指南中有一个例子:
7.3.处理部分send()
请记住上面关于send()的部分,当我说send()可能不会发送你要求它的所有字节时?也就是说,你希望它发送512个字节,但它返回412.剩下的100个字节发生了什么?
好吧,他们还在你的小缓冲区等待被送出去.由于你无法控制的情况,内核决定不在一个块中发送所有数据,而现在,我的朋友,由你来获取数据.
您也可以编写这样的函数来执行此操作:
int sendall(int s, char *buf, int *len)
{
int total = 0; // how many bytes we've sent
int bytesleft = *len; // how many we have left to send
int n;
while(total < *len) {
n = send(s, buf+total, bytesleft, 0);
if (n == -1) { break; }
total += n;
bytesleft -= n;
}
*len = total; // return number actually sent here
return n==-1?-1:0; // return -1 onm failure, 0 on success
}
Run Code Online (Sandbox Code Playgroud)
编辑:正如@alk所指出的那样,将所有ints 替换为ssize_t- 返回的类型send()
如果您正在发送或接收UDP数据包,那么就无法绕过它; 你需要一个足够大的缓冲区来容纳整个数据包.幸运的是,在大多数情况下,您不希望发送或接收大于1500字节的UDP数据包(因为这是以太网卡可以发送的最大数据包而不会将其分成更小的数据包,并且通常您希望避免碎片,如果可能).
对于TCP,请记住您正在发送/接收字节流,而不是一系列单独的数据包,因此传递给send()和recv()的大小通常不会对应于网络的大小然后包.这意味着调用send()6次,每次调用100个字节的数据,与使用600字节数据调用send()1次没有太大区别,依此类推.正如其他人所指出的那样,你必须仔细检查每个send()和recv()调用的返回值,以查看实际发送或接收的字节数,因为发送/接收的数量有时可能(并且会)小于您请求的字节数.您需要知道实际发送了多少字节才能知道哪些字节适合在下次调用时发送,并且您需要知道实际接收了多少字节才能知道您的接收中现在有多少字节有效 - 缓冲.