【问题标题】:How to determine end of read如何确定读取结束
【发布时间】:2013-12-18 19:23:13
【问题描述】:

我有简单的 C 服务器和 Java 客户端。我正在从服务器到客户端逐行发送文本文件:

    do {
        send(sockfd, line, strlen(line), 0);
        printf("%s\n", line);
    } while ((fgets(line, 100, fp)) != NULL);  

并在 Java 客户端中读取它:

    Client.getCl().getInputStream().read(inmsg);
    do{             
         decoded = new String(inmsg, "UTF-8");
         System.out.println(decoded);
    }while(Client.getCl().getInputStream().read(inmsg) > 0);  

我的问题是我不知道如何将“读取结束”从服务器发送到客户端。客户端在上次读取时冻结。我知道methode read() 返回带有接收字节数的整数,当没有要读取的内容时返回-1,当缓冲区长度为零时返回0。向客户端返回 -1 的唯一解决方案是关闭服务器端的套接字,但我不能使用它。我也试过以下:
1) 在发送方法结束时发送 0 长度告诉客户端,该长度为零:

send(sockfd, NULL, NULL, 0);  

2) 定义标志并发送:

#define MSG_FIN 0x200
#define MSG_EOR 0x0080

再次使用两个标志:

 send(sockfd, NULL, NULL, MSG_FIN);
 send(sockfd, NULL, NULL, MSG_EOR);  

任何人请帮助我在这里做错了什么?谢谢

【问题讨论】:

  • 我知道你说你不能使用它,但是为什么你不能关闭服务器上的套接字?如果您不愿意关闭它,那是不是意味着您以后要发送其他东西?如果是这样的话,那么 Java 应该仍然可以读取,对吧?
  • 您可能需要提前确定要发送多少字节,并在数据前加上该数字,以便客户端可以确定何时停止读取。就像 HTTP 中的 Content-Length header
  • 如果您需要通过 TCP 连接发送不同的“消息”,这是您必须自己实现和处理的应用程序级问题。 TCP 并不真正关心这一点。 (UDP 可以,但它的不可靠性可能使其不适合您的用例。即不适合媒体流或 P2P。)
  • 现在,除非这是一项学校作业,否则我要做的是获得某种确实处理此问题的消息传递中间件。我能想到的适用于 C 和 Java 的最简单的可能是 0MQ。如果您的用例是基于文本的,您还可以执行 HTTP 所做的那样,其中空行表示请求标头的结束——您当然必须确保在发送消息后显式刷新套接字。当客户端收到一个空行时,它会去做其他事情,然后再回到套接字。

标签: java c inputstream ansi server-communication


【解决方案1】:

如果您想通过同一个 TCP 套接字发送间歇性数据,您需要在您发送的数据中对您发送的信息的边界进行编码。这方面的一个例子是发送带有长度前缀的数据“数据包”,这样数据包的接收者就会从套接字中读取与长度前缀所说的一样多的字节。

【讨论】:

  • +1 接收者唯一知道的是流的结束。如果你想让它知道“消息”,你需要添加一个协议来做到这一点。例如在每条消息之前发送一个 4 字节长度,以便它知道要读取多少。
  • 现在我首先发送多行文件,然后行本身和客户端读取的次数与数字所说的一样多。谢谢
【解决方案2】:

你的读者有两个问题。您假设您将始终读取完整的缓冲区。除非您一次只读取一个字节,否则您不能假设这一点。您还假设您将始终读取整个多字节字符,除非您从不使用多字节字符,否则这不太可能是真的。

由于您正在编写文本,我建议您在消息之间发送新行并将流作为文本读取。

BufferedReader br = new BufferedReader(new InputStreamReader(
                        Client.getCl().getInputStream(), "UTF-8"));
for(String line; (line = br.readLine()) != null; ) {
    // process a whole line of text at once. e.g.
    System.out.println(line);
}

这将解码文本、读取整行并处理任何多字节字符。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-26
    • 2023-04-06
    • 2021-02-01
    • 1970-01-01
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多