【问题标题】:UDP socket Datagram receive packet 2x to get full messageUDP 套接字数据报接收数据包 2x 以获取完整消息
【发布时间】:2011-12-30 19:09:40
【问题描述】:

我正在Java 中构建一个实验性游戏服务器。

客户端发送:

length: 22\r\n
playerId: 0\r\n
\r\n\r\n
this is a test message

Java接收消息的代码:

String message = "";

byte[] buf = new byte[20];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socketServer.receive(packet);
message += new String(buf, "UTF8");

buf = new byte[20];
packet = new DatagramPacket(buf, buf.length);
socketServer.receive(packet);
message += new String(buf, "UTF8");

这不会收到客户端发送的消息的 40 个字节,它接收 20 个字节,然后在第二个 socketServer.receive(packet) 它挂起等待新消息。

原因:

此方法阻塞,直到收到数据报。长度字段 数据报包对象包含接收到的长度 信息。如果消息长于数据包的长度,则 消息被截断。

我需要能够读取 20 个字节的消息和另外 20 个字节的消息。如何实现?

我需要这个,因为我不确定消息会持续多久。我想要这样的东西:

String message = "";
while (!message.contains("\r\n\r\n")) { //"\r\n\r\n" marks end of message
    byte[] buf = new byte[20];
    DatagramPacket packet = new DatagramPacket(buf, buf.length);
    socketServer.receive(packet);
    message += new String(buf, "UTF8");
}

假设消息以 \r\n\r\n 结尾,这将得到完整消息。

需要通过UDP 协议完成。我是Java 中的套接字的新手,但我认为这有一些东西,只是找不到。提前致谢。

【问题讨论】:

    标签: java sockets networking udp


    【解决方案1】:

    UDP 并非为可变长度读取而设计 - 每个 read() [或 recv()] 将对应于服务器上的单个 write() [或 send()]。

    如果您只读取 40 字节数据包的 20 字节,则剩余字节将被丢弃。

    您需要创建一个足够大的缓冲区来接收整个数据包(如果您的网络正确处理分片,则最多 65536 字节),然后一次性读取整个数据包。

    API 会告诉您实际收到了多少字节 - 您应该考虑对照数据包内编码的值进行检查, 以确保您确实收到了整个数据包。

    【讨论】:

    • 这会影响性能吗?似乎将缓冲区设置得非常高可能很糟糕,我只是不知道。
    • @PatrickLorio 有 64k 缓冲区?一点也不 - 它只是一点点 RAM。
    • 一个UDP数据报的最大长度为65535-28字节。
    【解决方案2】:

    如果你写 40 个字节,你应该收到 40 个字节。如果你写了 40 个字节,而你的缓冲区只有 20 个,那么你会丢失 20 个字节。

    问:那么为什么不将缓冲区设为 256 字节(例如),然后读取你得到的任何内容?

    问:如果您需要“消息”分两部分到达……那为什么不只发送两条消息呢?

    【讨论】:

    • 因为假设我将缓冲区设置为 256 字节,而消息为 1024+,那么将缓冲区设置得非常大是否明智?
    • 那为什么不只发送两条消息?” - 因为 20 字节消息的每个数据包开销约为 300% ?
    • Q2:UDP 不是 100%,数据包会丢失,因此如果消息被分成两部分,则不能保证接收到完整的消息。
    • 这是我最近听到的最愚蠢的事情。如果需要 20 字节则发送 20 字节,如果需要 40 字节则发送 40 字节,如果需要检测丢弃的数据包,请使用 TCP 流或创建简单的“确认”协议。不要沉迷于“错误的优化”!
    猜你喜欢
    • 2014-05-14
    • 1970-01-01
    • 2015-11-28
    • 2015-11-26
    • 2013-03-23
    • 1970-01-01
    • 2011-03-30
    • 2013-08-28
    相关资源
    最近更新 更多