another Vala problem occured: I try to send and receive data via UDP. The sending works and via Wireshark I can see that the server sends the expected result. Problem is: My program doesn't get the data.
I checked and I can see that, when a socket has been created to send the UDP data, the specific port stays open, which is confirmed by Wireshark because my PC doesn't send any of those ICMP messages back to the server.
What I got so far:
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);}
What currently happens: The message is send, the string 'Response' is printed once into the console and after that it just loops.
If I check response.get_available()
it returns 0.
I can check with lsof | grep used_portnumber
and sure enough, the used socket stays open. What am I doing wrong?
I am not sure but this is what I suspect:
UDP is a datagram protocol (data is explicitly chopped into data). Server have sent one datagram to client. Now in BSD Sockets (and after it everywhere) if the underlaying socket have datagram type then read
reads the full packet. If the buffer have insufficient length the message is truncated.
The solution is read in one byte. For example
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);
Edit I have change the code to print UTF-8 text - without assuming current locale is "UTF-8"-based.
PS 1 This is my guess as it is one gotcha of BSD Sockets (also Winsockets and everything that builds on this) that come to my mind. Please be graceful if the question will be more specific (i.e. it is not the answer to question).
PS 2 In general I would recommend against mixing bytes and chars. While in ASCII-compatible encodings (ISO, UTF-8) sending ASCII subset of chars is safe it will bite when attempt on CJK encodings or if sender will send 'ą' by UTF-8 and sender will treat it as ISO-8859-2 (where this character have different encoding). I assume it is for the toy-examples only. If not you may want to read What Every Programmer Absolutely, Positively Needs To Know About Encodings And Character Sets To Work With Text.