编辑:在评论中已经证明,定义长度应该产生相同的结果,并且不会使用任何重要的额外数据。如果您正在寻找一种在运行程序的计算机之间发送数据的方法,那么发送长度比读取终止字符要好。 BonzaiThePenguin有一些非常好的观点,你应该看看。
但出于教育目的:我从来没有找到能够为标准C套接字执行此操作的良好示例代码,这些套接字处理的数据并非全部在一个数据包中接收,或者一个数据包中包含多个单独的消息。简单地重复调用recv并不适用于所有情况。
这是我自己在下面回答的问题之一,但我对自己的回答并不是100%自信。
答案 0 :(得分:1)
允许客户端指定正在发送的邮件的大小并不危险#39;。这个词中的大多数协议都是这样做的,包括HTTP和SSL。只有在实施不受限制的情况下才能正确检查消息,这才是危险的。
你的建议的致命缺陷是它不适用于二进制数据:你必须引入一个转义字符,以便终止字符可以出现在一个消息中,然后你当然也需要逃避逃逸。所有这些都增加了两端的处理和数据复制。
答案 1 :(得分:0)
这是我想出的。我不能保证这是完美的,因为我不是专业人士,所以如果有任何错误,我(以及其他寻求帮助的人)会非常感激,如果有人会指出它们。
上下文:socket是套接字,buffer是存储所有网络输入的数组,line是存储从缓冲区中提取的一条消息的数组(这是程序其余部分使用的),length是两者的长度输入数组,并且recvLength是指向存储在函数外部的整数的指针,该整数最初应为0,不应由其他任何内容释放或修改。也就是说,它应该在同一个套接字上多次调用此函数。此函数返回行数组中输出的数据的长度。
size_t recv_line(int socket, char* buffer, char* line, size_t length, size_t* recvLength){ //receives until '\4' (EOT character) or '\0' (null character)
size_t readHead = 0;
size_t lineIndex = 0;
char currentChar = 0;
while (1){
for (; readHead < *recvLength; readHead = readHead + 1){
currentChar = buffer[readHead];
if (currentChar=='\4' || currentChar=='\0'){ //replace with the end character(s) of your choice
if (DEBUG) printf("Received message===\n%s\n===of length %ld\n", line, lineIndex+1);
memcpy(buffer, buffer + readHead + 1, length-(readHead)); //shift the buffer down
*recvLength -= (readHead + 1); //without the +1, I had an "off by 1" error before!
return lineIndex+1; //success
}
if (readHead >= length){
if (DEBUG) printf("Client tried to overflow the input buffer. Disconnecting client.\n");
*recvLength = 0;
return 0;
}
line[lineIndex] = currentChar;
lineIndex++;
}
*recvLength = recv(socket, buffer + readHead, length, 0);
}
printf("Unknown error in recv_line!\n");
return 0;
}
简单示例用法:
int function_listening_to_network_input(int socket){
char netBuffer[2048];
char lineBuffer[2048];
size_t recvLength = 0;
while (1==1){
size_t length = recv_line(socket, netBuffer, lineBuffer, 2048, &recvLength);
// handle it…
}
return 0;
}
请注意,这并不总是将行保留为以null结尾的字符串。如果您愿意,可以轻松修改。