在C语言中从套接字读取消息

6

我尝试理解在C(Linux)中从套接字读取数据的过程,以下是代码的一部分:

while(success == 0) {

    while((n = read(sockfd, buffer, BUFFSIZE, 0)) > 0) {
        printf("%s",buffer);
        bzero(buffer,BUFFSIZE);
    }
    success = 1;
    printf("###");

}

信息已经被打印,但是三个井号(###)没有被打印出来?为什么?程序似乎在read()上被阻塞了。这里我只是打印了信息,但我需要做的是缓冲整个信息然后处理它。

6个回答

8

套接字的另一端程序没有关闭它,也没有关闭它的写入(这些是你的读取),因此你的端点不知道什么时候结束 - 实际上,逻辑上直到另一端说没有更多内容可供你读取才算结束。

通常,你的应用程序级别逻辑需要预先知道要读取多少内容,或者读取到特定终止符号,或者另一端正常关闭或关闭套接字。

(非阻塞I/O是完全不同的东西 - 它允许你在单个线程中高效地从套接字读取时做其他事情,但它不能解决确定何时从套接字读取完成的问题,这是你的问题。)


1
非常感谢,现在我正在逐个字符地将消息保存到缓冲区中,当我发现换行符时,我停止保存并进行处理 :) 然后我清除缓冲区并接收下一行。 - Asheron2332

5

你需要知道接收到的消息有多大,并一直阅读,直到获得整个消息(读取操作可能只返回消息的部分内容)。

do {
    nread = read(s, buf, to_read);
    if (nread < 0 && errno == EINTR)
            continue;
    if (nread < 0) {
            perror("read");
            exit(1);
    }

    if (nread == 0) {
            printf("socket closed");
            ... do something appropiate ...
            ... (reconnecting/exiting the loop with an error/...) ...
    }

    to_read -= nread;
    buf += nread;
} while (to_read > 0); 

to_read 是你期望读取的字节数。 buf 已经有足够的空间来存储这些数据。每次读取后,要相应地更新 to_readbuf。当然,你还需要正确地处理错误。


1

你必须知道何时停止从套接字读取数据,否则套接字将阻塞程序直到它接收到更多数据。如果想了解如何创建不会阻塞程序的套接字,请查看非阻塞套接字。

ief2


非阻塞IO如何解决读取足够数据的问题? - Will
非阻塞套接字在没有数据可用时会返回错误代码。我认为这篇文章很直接:http://www.scottklement.com/rpg/socktut/nonblocking.html - v1Axvw
这通常意味着数据尚未到达,而不是您已经读取了整个数据报/段/消息/任何内容。 - ninjalj
没错,不过我所说的也是正确的!没有数据可用。为了良好的通信,您将需要设置一个协议,即使它可能很小,比如只有一个32位整数。然后,您必须确保在继续之前接收到4个字节。这不是显而易见的吗? - v1Axvw

0

尝试添加\n。有时未结束的行不会被打印。

编辑:哦,等等,你是说程序没有结束?


0

我猜你的 while 循环永远不会终止,因为读取操作要么成功,要么阻塞。


我猜它会阻塞,但如何将整个消息读入内存,然后处理它呢? - Asheron2332
退出循环,例如 while ((n = read(sockfd, buffer, BUFFSIZE, 0)) > 0 && !done) - fizzer

0

你的 while 循环只有在 n 的值为零时才会结束。

你期望 read 什么时候返回零?你发送到该套接字的数据是否满足导致 read 返回零的任何条件?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接