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 本身内部的字节顺序可能不同。相反,您应该声明自己的 序列化协议 以及您的消息如何转换为二进制数据,反之亦然。
希望对你有帮助。
我想做一个聊天应用。客户端会写成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 本身内部的字节顺序可能不同。相反,您应该声明自己的 序列化协议 以及您的消息如何转换为二进制数据,反之亦然。
希望对你有帮助。