4

发生了另一个 Vala 问题:我尝试通过 UDP 发送和接收数据。发送有效,通过 Wireshark 我可以看到服务器发送了预期的结果。问题是:我的程序没有得到数据。

我检查了一下,我可以看到,当创建了一个套接字来发送 UDP 数据时,特定端口保持打开状态,Wireshark 确认了这一点,因为我的 PC 没有将任何这些 ICMP 消息发送回服务器。

到目前为止我得到了什么:

try
{
    SocketClient mySocket = new SocketClient();
    mySocket.protocol = SocketProtocol.UDP;
    mySocket.type = SocketType.DATAGRAM;
    var conn = mySocket.connect (new InetSocketAddress(addr,targetPort));
    conn.output_stream.write(themessage_in_a_uint8_array);
    DataInputStream response = new DataInputStream (conn.input_stream);
    string resp ="";
    char myChar;
    try
    {
        do
        {
            myChar = (char)response.read_byte();
            print ("Response" + myChar.to_string());
        }while(true);
    }
    catch(Error e)
    {
        print(e.message);
    }
}
catch(Error e)
{print(e.message);}

当前发生的情况:消息被发送,字符串“响应”被打印到控制台一次,然后它只是循环。

如果我检查response.get_available()它返回0。

我可以检查lsof | grep used_portnumber并确定,使用的套接字保持打开状态。我究竟做错了什么?

4

1 回答 1

1

我不确定,但这是我怀疑的:

UDP 是一种数据报协议(数据被明确地分割成数据)。服务器向客户端发送了一个数据报。现在在 BSD 套接字(以及它之后的任何地方)中,如果底层套接字具有数据报类型,则read读取完整的数据包。如果缓冲区的长度不足,则消息将被截断

解决方案以一个字节读取。例如

uint8[] buffer = new uint8[1 << 16]; // Maximum UDP length - we don't loose anything
unowned string locale;
bool need_convert = GLib.get_charset (out locale);
do {
    ssize_t len = response.read (buffer);
    string text;
    if (need_convert) {
        text = GLib.convert ((string)buffer, len, locale, "UTF-8");
    } else {
        text = (string)buffer;
    }
    stdout.print("Response " + text);
} while (true);

编辑我已更改代码以打印 UTF-8 文本 - 不假设当前语言环境是基于“UTF-8”的。

PS 1这是我的猜测,因为它是我想到的 BSD 套接字(还有 Winsockets 和基于此的所有东西)的一个陷阱。如果问题更具体(即不是问题的答案),请保持优雅。

PS 2一般来说,我建议不要混合字节和字符。虽然在 ASCII 兼容的编码(ISO、UTF-8)中发送字符的 ASCII 子集是安全的,但当尝试使用 CJK 编码或发送方将通过 UTF-8 发送“±”并且发送方会将其视为 ISO-8859 时,它会咬人2(这个字符有不同的编码)。我认为它仅适用于玩具示例。如果没有,您可能想阅读每个程序员绝对需要了解的关于编码和字符集以使用文本的知识。

于 2012-12-25T00:58:31.107 回答