繁体   English   中英

从套接字读取C语言的数据直到结束字符

[英]Reading Data in C From Socket Until End Character

编辑:在评论中已经证明定义长度应该产生相同的结果,并且不会使用任何重要的额外数据。 如果您正在寻找一种在运行程序的计算机之间发送数据的方法,则发送长度比读取直到终止字符要好。 BonzaiThePenguin有一些非常好的方面您应该注意。

但是出于教育目的:我从来没有找到好的示例代码来为标准C套接字执行此操作,该标准C套接字处理的情况是,一个包中未全部接收数据,或者一个包中包含多个单独的消息。 简单地反复调用recv并非在所有情况下都可行。

这是我自己在下面回答的问题之一,但是我对自己的回答没有100%的信心。

“允许客户端指定要发送的消息的大小不是危险的”。 这个词中的大多数协议都可以做到这一点,包括HTTP和SSL。 仅当实现未正确对消息进行边界检查时,这才是危险的。

建议的致命缺陷是它不适用于二进制数据:您必须引入转义符,以便终止符可以出现在消息中,然后当然也需要转义。 所有这些都在两端增加了处理和数据复制。

这是我想出的。 我不能保证这是完美的,因为我不是专业人士,所以如果有任何错误,如果有人指出,我(以及其他寻求帮助的人)将不胜感激。

上下文: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;
}

请注意,这并不总是将行保留为以空值结尾的字符串。 如果您愿意,可以轻松进行修改。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM