On Fri, 07 Mar 2014 22:48:49 GMT, hardcoder wrote:

Hi,

I am evaluating Vibe.d for my next project. It will be used as a TCP and UDP server.

I just compiled basic TCP example but the momnet I wanted to do simple change things started to work unexpectedly.

In my simple example client app just writes bytes to socket and then starts reading.

Things work ok when handler looks like this:

void onConnection(TCPConnection conn)
{
  conn.write(conn);
}

but when I change it to:

void onConnection(TCPConnection conn)
{
  auto data = conn.readAll;
  conn.write(data);
}

handler never writes data back because readAll() blocks. In other thread I found the answer: realAll() blocks until client closes connection. Answer also suggests readLine() but in my case it wont work as data is binary.

My question: how to read InputStream the same way conn.write(conn) does in the first version?

You can get really creative interacting with the TCPConnection with just conn.read(dst) and conn.write(src). There's a lot of helpers if you look around in the library but here's a few ways: 1) you can use the primitives, 2) you can use readLine() by making sure you write a \n after every statement or 3) you could also push some objects directly down the stream using a serialization library.

1) The most common way is to allocate the destination bytes and simply read to them:

while (conn.waitForData(5.seconds)){
	ubyte[] len = new ubyte[1];
	conn.read(len);
	ubyte[] data = new ubyte[len];
	conn.read(data);
}

(2) You can send the data followed by a line separation
conn.write(cast(ubyte[])"hello there\n")
and on the other end:
auto recv = conn.readLine();

(3) Using a serialization library like msgpack-d you can send your objects and rebuild them at the other end of your tcp connection. In vibe you have json serialization or you can also use msgpack-d
https://github.com/msgpack/msgpack-d

import std.file;
import msgpack;

struct S { int x; float y; string z; }

void onConnection(TCPConnection conn)
{
	S input = S(10, 25.5, "message");

	// serialize data
	ubyte[] inData = pack(input);
	
	// write data to the stream
	conn.write(inData);
}

on the other end...

void onConnection(TCPConnection conn)
{
	S input = S(10, 25.5, "message");
	// read data from a file
	ubyte[] outData = new ubyte[150];
	
	conn.read(outData);
	
	// unserialize the data
	S target = outData.unpack!S();
	
	// verify data is the same
	assert(target.x == input.x);
	assert(target.y == input.y);
	assert(target.z == input.z);
}

Note that you could use another type of buffering mechanism to read the data to such as a FixedRingBuffer I gave it 150 ubytes for simplification.

Hope it helps!