[D]dasocks - Async Sockets

12/01/2014 21:32 Super Aids#1
As I'm working on a new server written in D then I've been working on implementing asynchronous sockets. The sockets should be able to run on any Windows and Posix (Linux, OSX etc.) based systems.

It uses the standard library, no 3rd party libraries and is compatible with DMD2.

The following modules from the standard library is used:
core.thread
[Only registered and activated users can see links. Click Here To Register...]
std.socket
[Only registered and activated users can see links. Click Here To Register...]
std.c.string
-- Standard C Library <string.h>
[Only registered and activated users can see links. Click Here To Register...]
std.array
[Only registered and activated users can see links. Click Here To Register...]
std.conv
[Only registered and activated users can see links. Click Here To Register...]
std.string
[Only registered and activated users can see links. Click Here To Register...]

The library provides the following modules:
asynctcpsocket.d
-- The socket wrapper for an asynchronous tcp socket
asyncthread.d
-- The thread wrapper for an asynchronous socket thread
error.d
-- The wrapper for exceptions
events.d
-- The event wrapper for events across the library
package.d
-- The package import (Makes it possible to do import dasocks;)
packet.d
-- A datapacket wrapper (Supporting a string packer too.)
states.d
-- A state wrapper
thread.d
-- A threading wrapper to provide possibility of events to be called whenever a new thread is run
uid.d
-- An UID generator

The zip archive includes the following:
All modules in the dasocks library
example.d (A simple example usage of the library -- Same as provided in the thread.)
cmd.txt (A text file containing the command line argument to compile example.d along with dasocks.)

All modules are documented.

example.d
Code:
import dasocks;

// Only required for bind() and Client test
import std.socket : InternetAddress, TcpSocket;
import std.stdio;

void main() {
	// Creates an asynchronous socket server
	auto server = new AsyncTcpSocket;
	// Sets the events of the server
	server.setEvents(new AsyncSocketEvent(&onAccept), new AsyncSocketEvent(&onReceive), new AsyncSocketEvent(&onDisconnect));
	// Begins to accept a connection
	server.beginAccept();	
	// Binds the server to 127.0.0.1:9988
	server.bind(new InternetAddress("127.0.0.1", 9988));
	// Starts listening for connections
	server.listen(500);
	
	// Client test ...
	writeln("Press ENTER to connect...");
	readln();
	// Creates a new NON-asynchronous tcp socket
	auto client = new TcpSocket;
	// Connects to 127.0.0.1:9988
	client.connect(new InternetAddress("127.0.0.1", 9988));
	writeln("Connected...");
	while (true) {
		writeln("Press ENTER to send a packet...");
		readln();
		// Creates a 10 byte packet
		ubyte[] buffer = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
		// Sends the packet
		client.send(buffer);
	}
}

void onAccept(AsyncTcpSocket server) {
	// Ends the acceptance of a socket and returns the accepted socket
	auto socket = server.endAccept();
	writeln("Socket[", socket.socketId, "] has connected.");
	// Begins to receive a 10 byte packet from the accepted socket
	socket.beginReceive(10);
	
	// Begins to accept a new connection
	server.beginAccept();
}

void onReceive(AsyncTcpSocket client) {
	import std.conv : to;
	
	// Gets the received packet from the client
	ubyte[] buffer = client.endReceive();
	string outStr;
	foreach (b; buffer)
		outStr ~= to!string(b) ~ ", ";
	outStr.length -= 2;
	writeln("[", outStr, "] from Socket[", client.socketId, "]");
	
	// Begins to receive a 10 byte packet from the client
	client.beginReceive(10);
}

void onDisconnect(AsyncTcpSocket socket) {
	if (socket.listening) {
		// If the socket is listening then it's a server socket
		writeln("The server was shutdown!");
	}
	else {
		// If the socket isn't listening then it's a client
		writeln("Socket[", socket.socketId, "] has disconnected.");
	}
}
Download:
[Only registered and activated users can see links. Click Here To Register...]

If you got trouble or have any questions feel free to ask.

For more information visit:
[Only registered and activated users can see links. Click Here To Register...]
12/21/2014 16:53 KraHen#2
@OP : Have you tried to benchmark this implementation against something like boost::asio or the standard .NET socket implementation? I`d be curious of the performance difference, say 10k clients.
12/21/2014 17:29 Best Coder 2014#3
Quote:
Originally Posted by KraHen View Post
@OP : Have you tried to benchmark this implementation against something like boost::asio or the standard .NET socket implementation? I`d be curious of the performance difference, say 10k clients.
It's doing lots of (unnecessary) allocations, from what I see it's basically written in like 99% C# style so I'm guessing it wasn't meant to be super high-performance. The project description doesn't state anything about performance either.
12/22/2014 00:15 Super Aids#4
Quote:
Originally Posted by KraHen View Post
Thank you for the slightly racist and totally unconstructive comment wasting around 100 bytes of memory somewhere in the epvp cloud.

@OP : Have you tried to benchmark this implementation against something like boost::asio or the standard .NET socket implementation? I`d be curious of the performance difference, say 10k clients.
I haven't done any benchmarks.

Quote:
Originally Posted by Best Coder 2014 View Post
It's doing lots of (unnecessary) allocations, from what I see it's basically written in like 99% C# style so I'm guessing it wasn't meant to be super high-performance. The project description doesn't state anything about performance either.
It was my first attempt ever to write asynchronous sockets in D and my goal was really just to have it working.

Working on something way more optimized though.