Java 中的 TCP 客户端和 C 中的服务器

TCP client in Java and server in C

我想做一个聊天应用。客户端会写成java,服务端会写成C。在服务端,消息会作为struct发送。在客户端,如何读取消息并将消息与 Java 分开?

这是一个示例数据包结构:

struct s_packet{
 int   text_color;
 char  text[TEXTSIZE];
 char  alias[ALIASIZE];
};

这是一个示例服务器(C 语言)发送函数:

send(iter->client.sockfd, (void *)se_packet, sizeof(s_packet), 0);

这是 C:

中的示例客户端 recv 函数
recv(m_sockfd, (void *)&se_packet, sizeof(s_packet),0);

printf("\x1b[3%dm <%s>: %s \x1b[0m\n", se_packet.text_color, se_packet.alias, se_packet.text);

我可以在 C 中阅读 s_packet 和分离,但我如何在 java 中做到这一点?

我怎么能像Java那样分开:

printf("\x1b[3%dm <%s>: %s \x1b[0m\n", se_packet.text_color, se_packet.alias, se_packet.text);

肯定的答案是不会那么容易。您应该了解的第一件事是 tcp 是如何工作的。 它是一个面向流的协议,在 tcp 中没有 "message" 这样的东西。您只需发送和接收字节流。

在您的代码片段中 recv 可以在读取从服务器发送的部分消息后完成。相反,您应该在 java 中保留一个本地缓冲区,并删除您目前收到的所有数据。在 while 循环中,您可以检测是否收到了准备好进行处理的消息。如果您的消息不是很大(小于 MTU),那么您可能会很幸运并且总是收到整个 'message'。如果您不关心,那么您可以使用 java.io.InputStream.read(byte[]) 方法。

要考虑的另一件事是您如何解读收到的消息。 你别无选择,只能将其处理为 Java 中的 byte[]。 首先你可能想阅读 s_packet.text_color。它可能会作为消息中的前 4 个字节放置。您可以从这些字节构造 int(请参阅 Convert 4 bytes to int for example). But this is not a good practice. This is because you send a binary data that is depends on how your s_packet is represented in memory。在现实生活中,您通常不知道 int 或 char 的大小是多少,它取决于平台。或者有时 int 本身内部的字节顺序可能不同。相反,您应该声明自己的 序列化协议 以及您的消息如何转换为二进制数据,反之亦然。 希望对你有帮助。