Skip to content

Simple Socket Server Example

Jacob Jensen edited this page Sep 10, 2016 · 2 revisions

Below is a simple socket server example using cheetah.

module simple_socket_server_example;

import vibe.d : logInfo;

import cheetah;

shared static this() {
  // Creates a server listening at 127.0.0.1:8899
  auto server = new SocketServer!Client("127.0.0.1", 8899);

  // Attaches events to the server
  server.attach(SocketEventType.connect, new SocketEvent!Client(&onConnect));
  server.attach(SocketEventType.receive, [
    new SocketEvent!Client(&onReceiveHead),
    new SocketEvent!Client(&onReceiveBody)
  ]);
  server.attach(SocketEventType.disconnect, new SocketEvent!Client(&onDisconnect));
  server.attach(SocketEventType.error, new SocketEvent!Client(&onError));

  // Sets up events that has to be local per client.
  // This is usually used with events using moveNext() ...
  server.copyReceiveEvents = true;

  // Starts the server
  server.start();
}

/// Custom client wrapper that we use to handle custom packet specifications
class Client {
  size_t expectedAmount;
  ushort type;
}

/// Handling connections
void onConnect(SocketEventArgs!Client e) {
  logInfo("A client has connected ...");

  e.client.data = new Client;
}

/// Handling disconnections
void onDisconnect(SocketEventArgs!Client e) {
  logInfo("A client has disconnected ...");
}

/// Handling receive for the packet head
void onReceiveHead(SocketEventArgs!Client e) {
  e.client.read(4 - e.currentReceiveAmount);

  if (e.currentReceiveAmount >= 4) {
    auto ptr = e.buffer.ptr;

    e.client.data.expectedAmount = (*cast(ushort*)(ptr));
    e.client.data.type = (*cast(ushort*)(ptr + 2));

    logInfo("Received head ...");
    import std.conv : to;
    logInfo(to!string(e.client.data.expectedAmount));
    logInfo(to!string(e.client.data.type));

    e.resetReceive(e.currentReceiveAmount);
    e.client.moveNext(SocketEventType.receive);
  }
}

/// Handling receive for the packet body
void onReceiveBody(SocketEventArgs!Client e) {
  e.client.read(e.client.data.expectedAmount - e.currentReceiveAmount);

  if (e.currentReceiveAmount >= e.client.data.expectedAmount) {
    logInfo("Received body ...");
    import std.conv : to;
    logInfo(to!string(e.buffer[4 .. $]));

    e.resetReceive(e.currentReceiveAmount - e.client.data.expectedAmount);
    e.client.moveNext(SocketEventType.receive);
  }
}

/// Handling errors
void onError(SocketEventArgs!Client e) {
  logInfo("Error: " ~ e.error.toString());

  if (e.client) {
    e.client.close();
  }
  else if (e.server) {
    e.server.stop();
  }
}
Clone this wiki locally