`Socket.receive` providing arbitrary packet sizes and hanging without sending EOF

Unazed Spectaculum unazed at spec.org
Thu Dec 14 19:55:46 UTC 2017


On Thursday, 14 December 2017 at 00:09:39 UTC, Ali Çehreli wrote:
> On 12/13/2017 11:39 AM, Unazed Spectaculum wrote:
> > ubyte[] receiveBytes(T)(T socket, size_t receiveCount)
> > {
> >      ubyte[] buffer = new ubyte[receiveCount];
> >      size_t count = socket.receive(buffer);
>
> Don't trust code you find on newsgroups. :o) You have to check 
> the returned value first. According to documentation, it can 
> return Socket.ERROR:
>
>   https://dlang.org/phobos/std_socket.html#.Socket.receive
>
> > there is always a superfluous chunk
> > which is awaiting data.
>
> Can you show with complete code? Perhaps the stream is in 
> blocking mode?
>
> > No matter what way I try; my code doesn't seem to know when
> to quit
> > regardless of the check. Also for the arbitrary packet sizes,
> I would've
> > expected that if I received N bytes X times, the first X-1
> times would
> > be perfectly N not some unusual integer.
> > Simply put, say I'm receiving 1024 bytes 5 times. The length
> of each
> > item on the stack looks like:
> >
> > [720,
> >   490,
> >   1024,
> >   103
> > ]
>
> Posix read(2) man page says
>
> "It is not an error if this number is smaller than the number 
> of bytes
> requested; this may happen for example because fewer bytes are 
> actually
> available right now (maybe because we were close to 
> end-of-file, or because
> we are reading from a pipe, or from a terminal), or because 
> read() was
> interrupted by a signal."
>
> Ali

void main()
{
	auto socket = new TcpSocket();
	setupSocket(socket, "0.0.0.0", 6969);
	
	writefln("Listening: %s", socket.localAddress);

	while(true)
	{
		Socket client = socket.accept();
		debug(1) writefln("Client: %s", client.remoteAddress);

		auto data = receiveAll(client);
		writeln(data);
		JSONValue json;

		try {
			json = parseJSON(data);
		} catch (JSONException e) {
			debug(1) writefln("Failed parsing data as JSON, aborting.\n|| 
%s", e);
			client.close();
			continue;
		} catch (Exception e) {
			debug(1) writefln("Client caused exception:\n||%s", e);
			client.close();
			continue;
		}

		if (!verifyValues(json))
		{
			debug(1) writefln("Client missed out important key fields: 
%s", client.remoteAddress);
			client.close();
			continue;
		}

		debug(1) writeln("Client transacted successful JSON packet.");

		writefln("%s:\n\tFilename: %s\n\tMethod: %s\n\tData length: %d",
				client.remoteAddress,
				json["filename"],
				json["method"],
				data.length
			);

		if (json["method"].str == "store")
			storeData(json["filename"].str, json["data"].str);
		else if (json["method"].str == "retrieve")
			retrieveData(client, json["filename"].str);

		client.close();
	}
}

This is the only function which has a call to `receiveAll`, also 
yeah I don't typically check return codes for error values, I 
just assume it'll all work and if it doesn't a fresh restart will 
fix it; but I'll include it in my code just in case.


More information about the Digitalmars-d-learn mailing list