Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Net;
- using System.Net.Sockets;
- using System.Collections.Generic;
- using System.Threading.Tasks;
- using System.Linq;
- using System.Text;
- namespace SOQAsyncQuit
- {
- public class TcpListenerEx : TcpListener
- {
- public TcpListenerEx(IPEndPoint localEndPoint) : base(localEndPoint)
- {
- }
- public TcpListenerEx(IPAddress localAddress, int localPort) : base(localAddress, localPort)
- {
- }
- public new bool Active
- {
- get {
- return base.Active;
- }
- }
- }
- class MainClass
- {
- protected static IDictionary<TcpListenerEx, IList<TcpClient>> servers = new Dictionary<TcpListenerEx, IList<TcpClient>>();
- public static void Main (string[] args)
- {
- Log("Initializing...");
- // Define listeners.
- TcpListener s1 = CreateAndStartServer(IPAddress.Any, 1337);
- TcpListener s2 = CreateAndStartServer(IPAddress.Any, 1338);
- // Start async.
- Task.Factory.StartNew(Accept, s1);
- Task.Factory.StartNew(Accept, s2);
- // Wait for connections only if servers active.
- while (servers.Any(s => s.Key.Active))
- {
- // 100% usage.
- }
- Log("Nothing left to do, stopping service.");
- }
- /// <summary>
- /// Convenience method to create and start a server in "one call".
- /// </summary>
- /// <returns>The started server.</returns>
- /// <param name="address">Address the server should listen to.</param>
- /// <param name="port">Port the server should respond to.</param>
- public static TcpListenerEx CreateAndStartServer(IPAddress address, int port)
- {
- TcpListenerEx server = new TcpListenerEx(address, port);
- IList<TcpClient> clients = new List<TcpClient>();
- servers.Add(server, clients);
- IPEndPoint endPoint = server.LocalEndpoint as IPEndPoint;
- Log("Starting for {0}", endPoint);
- server.Start();
- return server;
- }
- /// <summary>
- /// Client acceptor.
- /// </summary>
- /// <param name="state">The server to accept from.</param>
- public static async void Accept(object state)
- {
- TcpListenerEx server = (TcpListenerEx) state;
- IPEndPoint endPoint = server.LocalEndpoint as IPEndPoint;
- Log("Accepting clients on {0}", endPoint);
- while (true)
- {
- var client = await server.AcceptTcpClientAsync();
- if (client == null)
- {
- Log("Null error on accept");
- break;
- }
- TcpClient connected = (TcpClient) client;
- servers[server].Add(connected);
- bool stop = await Task<Task<bool>>.Factory.StartNew(Listen, connected).Unwrap();
- if (stop == true)
- {
- break;
- }
- }
- // Stop the server.
- server.Stop();
- Log("Stoppped {0}", endPoint);
- }
- /// <summary>
- /// Client listener.
- /// </summary>
- /// <param name="state">The client to listen to.</param>
- public static async Task<bool> Listen(object state)
- {
- TcpClient client = (TcpClient) state;
- NetworkStream connectionStream = client.GetStream();
- // Extract server information.
- KeyValuePair<TcpListenerEx, IList<TcpClient>> serverInformation = servers.First(x => x.Value.Contains(client));
- TcpListenerEx server = serverInformation.Key;
- IList<TcpClient> clients = serverInformation.Value;
- IPEndPoint endPoint = client.Client.RemoteEndPoint as IPEndPoint;
- byte[] buffer = new byte[4096];
- Log("Client {0} connected to {1}", endPoint, server.LocalEndpoint);
- Encoding encoding = Encoding.UTF8;
- Random randomizer = null;
- // Are we still listening?
- bool listening = true;
- // Stop the server afterwards?
- bool stop = false;
- while (listening)
- {
- int bytesRead = await connectionStream.ReadAsync(buffer, 0, buffer.Length);
- Log("[{0}] Bytes read: {1}", endPoint, bytesRead);
- if (bytesRead > 0)
- {
- // Create a new byte array for recieved data and populate
- // with data from buffer.
- byte[] messageBytes = new byte[bytesRead];
- Array.Copy(buffer, messageBytes, messageBytes.Length);
- // Generate a message from message bytes.
- string message = encoding.GetString(messageBytes);
- switch (message)
- {
- case "stop-server":
- Log("[{0}] Requested to stop: {1}", endPoint, server.LocalEndpoint);
- Respond(connectionStream, Message(encoding, "Stopping now..."));
- listening = false;
- stop = true;
- break;
- case "random":
- if (randomizer == null)
- {
- randomizer = new Random();
- }
- int random = randomizer.Next(1337);
- Log("[{0}] Generated random value: {1}", endPoint, random);
- Respond(connectionStream, Message(encoding, "Your random number: {0}", random));
- break;
- case "disconnect":
- Log("[{0}] Has requested to be disconnected", endPoint);
- Respond(connectionStream, Message(encoding, "Disconnecting..."));
- listening = false;
- break;
- default:
- Log("[{0}] Message: {1}", endPoint, message);
- break;
- }
- }
- if (bytesRead == 0 || listening == false)
- {
- Log("Disconnected");
- clients.Remove(client);
- client.Client.Dispose();
- break;
- }
- }
- return stop;
- }
- /// <summary>
- /// Convenience method to generate message and convert into bytes from a string.
- /// </summary>
- /// <param name="encoding">The encoding we should use for getting bytes.</param>
- /// <param name="format">The messages format.</param>
- /// <param name="replacements">Replacement data.</param>
- public static byte[] Message(Encoding encoding, string format, params object[] replacements)
- {
- string message = String.Format(format, replacements);
- byte[] bytes = encoding.GetBytes(message);
- return bytes;
- }
- /// <summary>
- /// Convenience method for sending and flushing data to stream.
- /// </summary>
- /// <param name="tunnel">The stream that we will be sending to.</param>
- /// <param name="message">The message that we are about to send.</param>
- public static void Respond(NetworkStream tunnel, byte[] message)
- {
- tunnel.Write(message, 0, message.Length);
- tunnel.Flush();
- }
- /// <summary>
- /// Convenience method for logging information to console.
- /// </summary>
- /// <param name="format">The messages format.</param>
- /// <param name="replacements">Replacement data.</param>
- public static void Log(string format, params object[] replacements)
- {
- // Date+time.
- string date = String.Format("[{0}]", DateTime.Now.ToString("O"));
- // Passed message.
- string message = String.Format(format, replacements);
- // Grouped.
- string[] messageParts = new string[] { date, message };
- // Formatted.
- string log = String.Join(" ", messageParts);
- Console.WriteLine(log);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement