2012-12-24 126 views
3

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

我检查了一下,我发现当创建一个套接字发送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检查,果然,所使用的插座保持打开状态。我究竟做错了什么?

回答

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(这个字符有不同的编码)。我认为这只是玩具例子而已。如果不是,您可能需要阅读What Every Programmer Absolutely, Positively Needs To Know About Encodings And Character Sets To Work With Text

+0

谢谢,这确实打印出来......有些东西!那么,现在如果你可以添加你的答案,就如何从这些'字节'中得到一个字符串(或字符),那很好!在Wireshark中,我可以清楚地看到那里的文本。 –

+0

我很确定我收到的文字是UTF8。你也可以解释1 << 16做什么? –

+1

@SteffenWinkler:我已经改变为在当前语言环境中打印文本(我正在从内存中写入,所以我很抱歉,如果它不编译/我已经忘记了一些东西)。 1 << 16是最大的UDP长度(长度是16位,所以我需要2^16。1 << n与2^n相同),并且64K不是太大的内存来担心它。 –