Thread overview
Extra packet sent when using socket/socketstream
Feb 06, 2012
Vidar Wahlberg
Feb 07, 2012
Vladimir Panteleev
Feb 07, 2012
Vidar Wahlberg
February 06, 2012
Here's a small program that doesn't do anything useful:
---
import core.thread;
import std.socket;
import std.socketstream;
import std.stdio;

void main() {
        auto socket = new TcpSocket(new InternetAddress("nethack.alt.org", 23));
        auto stream = new SocketStream(socket);
        stream.write(cast(char[])[0xff, 0xfb, 0x18, 0xff, 0xfa, 0x18, 0x00, 'x', 't', 'e', 'r', 'm', 0xff, 0xf0, 0xff, 0xfc, 0x20, 0xff, 0xfc, 0x23, 0xff, 0xfc, 0x27, 0xff, 0xfe, 0x03, 0xff, 0xfb, 0x01, 0xff, 0xfd, 0x05, 0xff, 0xfb, 0x21, 0xff, 0xfb, 0x1f, 0xff, 0xfa, 0x1f, 0x00, 0x50, 0x00, 0x18, 0xff, 0xf0]);
        //stream.flush();
        Thread.sleep(dur!("seconds")(1));
        char[4096] data;
        auto count = stream.readBlock(&data, data.length);
        writefln("%s - %s", count, data[0 .. count]);
        stream.write(cast(char[])"l");
        //stream.flush();
        Thread.sleep(dur!("seconds")(1));
        count = stream.readBlock(&data, data.length);
        writefln("%s - %s", count, data[0 .. count]);
}
---

I'm seeing some peculiar results when executing this program. That is, I captured the data transmitted to nethack.alt.org using Wireshark and saw the following data being sent:
Telnet packet 1 (timestamp: 1.526691):
0000   2f 00 00 00 00 00 00 00

Telnet packet 2 (timestamp: 1.702938):
0000   ff fb 18 ff fa 18 00 78 74 65 72 6d ff f0 ff fc
0010   20 ff fc 23 ff fc 27 ff fe 03 ff fb 01 ff fd 05
0020   ff fb 21 ff fb 1f ff fa 1f 00 50 00 18 ff f0

Telnet packet 3 (timestamp: 2.528467):
0000   01 00 00 00 00 00 00 00


The second packet is identical to the data in my first call to "stream.write()", but why did it send "2f 00 00 00 00 00 00 00" (2f hex == 47 dec, which is the length of the first char-array I sent to "stream.write()") first?
It does the same thing for "l", which causes the server to hang up the connection before it even gets to send that "l".

I've tried the same thing in C++ (using sys/socket), that does not send a packet first telling how large the following packet will be, neither does simply "telnet nethack.alt.org".
I've also tried a number of ways to set up the socket:
new Socket(AddressFamily.INET, SocketType.[STREAM,RAW,SEQPACKET], ProtocolType.[TCP,IP,RAW]);

SocketType.SEQPACKET is apparently not supported on my system, and ProtocolType.RAW gives compilation error "Error: no property 'RAW' for type 'int'".


How can I make it not send a packet warning the recipient that it's about to receive another packet (of a given size)?
February 07, 2012
On Monday, 6 February 2012 at 21:51:54 UTC, Vidar Wahlberg wrote:
> How can I make it not send a packet warning the recipient that it's about to receive another packet (of a given size)?

Don't use std.socketstream. Streams serialize some types in an internal format (in your case, prepending the length of arrays). If you only need to operate on raw bytes, it's simple to use std.socket directly.
February 07, 2012
On 2012-02-07 14:44, Vladimir Panteleev wrote:
> On Monday, 6 February 2012 at 21:51:54 UTC, Vidar Wahlberg wrote:
>> How can I make it not send a packet warning the recipient that it's
>> about to receive another packet (of a given size)?
>
> Don't use std.socketstream. Streams serialize some types in an internal
> format (in your case, prepending the length of arrays). If you only need
> to operate on raw bytes, it's simple to use std.socket directly.

Thanks, that did the trick.