Advertisement
Guest User

Async, Threads, Waiting to finish.

a guest
May 29th, 2014
298
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.58 KB | None | 0 0
  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.Collections.Generic;
  5. using System.Threading.Tasks;
  6. using System.Linq;
  7. using System.Text;
  8.  
  9. namespace SOQAsyncQuit
  10. {
  11.     public class TcpListenerEx : TcpListener
  12.     {
  13.         public TcpListenerEx(IPEndPoint localEndPoint) : base(localEndPoint)
  14.         {
  15.         }
  16.  
  17.         public TcpListenerEx(IPAddress localAddress, int localPort) : base(localAddress, localPort)
  18.         {
  19.         }
  20.  
  21.         public new bool Active
  22.         {
  23.             get {
  24.                 return base.Active;
  25.             }
  26.         }
  27.     }
  28.  
  29.     class MainClass
  30.     {
  31.         protected static IDictionary<TcpListenerEx, IList<TcpClient>> servers = new Dictionary<TcpListenerEx, IList<TcpClient>>();
  32.  
  33.         public static void Main (string[] args)
  34.         {
  35.             Log("Initializing...");
  36.  
  37.             // Define listeners.
  38.             TcpListener s1 = CreateAndStartServer(IPAddress.Any, 1337);
  39.             TcpListener s2 = CreateAndStartServer(IPAddress.Any, 1338);
  40.  
  41.             // Start async.
  42.             Task.Factory.StartNew(Accept, s1);
  43.             Task.Factory.StartNew(Accept, s2);
  44.  
  45.             // Wait for connections only if servers active.
  46.             while (servers.Any(s => s.Key.Active))
  47.             {
  48.                 // 100% usage.
  49.             }
  50.  
  51.             Log("Nothing left to do, stopping service.");
  52.         }
  53.  
  54.         /// <summary>
  55.         /// Convenience method to create and start a server in "one call".
  56.         /// </summary>
  57.         /// <returns>The started server.</returns>
  58.         /// <param name="address">Address the server should listen to.</param>
  59.         /// <param name="port">Port the server should respond to.</param>
  60.         public static TcpListenerEx CreateAndStartServer(IPAddress address, int port)
  61.         {
  62.             TcpListenerEx server = new TcpListenerEx(address, port);
  63.             IList<TcpClient> clients = new List<TcpClient>();
  64.  
  65.             servers.Add(server, clients);
  66.  
  67.             IPEndPoint endPoint = server.LocalEndpoint as IPEndPoint;
  68.  
  69.             Log("Starting for {0}", endPoint);
  70.             server.Start();
  71.  
  72.             return server;
  73.         }
  74.  
  75.         /// <summary>
  76.         /// Client acceptor.
  77.         /// </summary>
  78.         /// <param name="state">The server to accept from.</param>
  79.         public static async void Accept(object state)
  80.         {
  81.             TcpListenerEx server = (TcpListenerEx) state;
  82.  
  83.             IPEndPoint endPoint = server.LocalEndpoint as IPEndPoint;
  84.  
  85.             Log("Accepting clients on {0}", endPoint);
  86.  
  87.             while (true)
  88.             {
  89.                 var client = await server.AcceptTcpClientAsync();
  90.  
  91.                 if (client == null)
  92.                 {
  93.                     Log("Null error on accept");
  94.                     break;
  95.                 }
  96.  
  97.                 TcpClient connected = (TcpClient) client;
  98.                 servers[server].Add(connected);
  99.  
  100.                 bool stop = await Task<Task<bool>>.Factory.StartNew(Listen, connected).Unwrap();
  101.  
  102.                 if (stop == true)
  103.                 {
  104.                     break;
  105.                 }
  106.             }
  107.  
  108.             // Stop the server.
  109.             server.Stop();
  110.  
  111.             Log("Stoppped {0}", endPoint);
  112.         }
  113.  
  114.         /// <summary>
  115.         /// Client listener.
  116.         /// </summary>
  117.         /// <param name="state">The client to listen to.</param>
  118.         public static async Task<bool> Listen(object state)
  119.         {
  120.             TcpClient client = (TcpClient) state;
  121.             NetworkStream connectionStream = client.GetStream();
  122.  
  123.             // Extract server information.
  124.             KeyValuePair<TcpListenerEx, IList<TcpClient>> serverInformation = servers.First(x => x.Value.Contains(client));
  125.             TcpListenerEx server = serverInformation.Key;
  126.             IList<TcpClient> clients = serverInformation.Value;
  127.  
  128.             IPEndPoint endPoint = client.Client.RemoteEndPoint as IPEndPoint;
  129.  
  130.             byte[] buffer = new byte[4096];
  131.  
  132.             Log("Client {0} connected to {1}", endPoint, server.LocalEndpoint);
  133.  
  134.             Encoding encoding = Encoding.UTF8;
  135.  
  136.             Random randomizer = null;
  137.  
  138.             // Are we still listening?
  139.             bool listening = true;
  140.  
  141.             // Stop the server afterwards?
  142.             bool stop = false;
  143.  
  144.             while (listening)
  145.             {
  146.                 int bytesRead = await connectionStream.ReadAsync(buffer, 0, buffer.Length);
  147.  
  148.                 Log("[{0}] Bytes read: {1}", endPoint, bytesRead);
  149.  
  150.                 if (bytesRead > 0)
  151.                 {
  152.                     // Create a new byte array for recieved data and populate
  153.                     // with data from buffer.
  154.                     byte[] messageBytes = new byte[bytesRead];
  155.                     Array.Copy(buffer, messageBytes, messageBytes.Length);
  156.  
  157.                     // Generate a message from message bytes.
  158.                     string message = encoding.GetString(messageBytes);
  159.  
  160.                     switch (message)
  161.                     {
  162.                         case "stop-server":
  163.                             Log("[{0}] Requested to stop: {1}", endPoint, server.LocalEndpoint);
  164.  
  165.                             Respond(connectionStream, Message(encoding, "Stopping now..."));
  166.  
  167.                             listening = false;
  168.                             stop = true;
  169.                             break;
  170.  
  171.                         case "random":
  172.                             if (randomizer == null)
  173.                             {
  174.                                 randomizer = new Random();
  175.                             }
  176.  
  177.                             int random = randomizer.Next(1337);
  178.  
  179.                             Log("[{0}] Generated random value: {1}", endPoint, random);
  180.                             Respond(connectionStream, Message(encoding, "Your random number: {0}", random));
  181.                             break;
  182.  
  183.                         case "disconnect":
  184.                             Log("[{0}] Has requested to be disconnected", endPoint);
  185.  
  186.                             Respond(connectionStream, Message(encoding, "Disconnecting..."));
  187.  
  188.                             listening = false;
  189.                             break;
  190.                            
  191.                         default:
  192.                             Log("[{0}] Message: {1}", endPoint, message);
  193.                             break;
  194.                     }
  195.                 }
  196.  
  197.                 if (bytesRead == 0 || listening == false)
  198.                 {
  199.                     Log("Disconnected");
  200.  
  201.                     clients.Remove(client);
  202.  
  203.                     client.Client.Dispose();
  204.                     break;
  205.                 }
  206.             }
  207.  
  208.             return stop;
  209.         }
  210.  
  211.         /// <summary>
  212.         /// Convenience method to generate message and convert into bytes from a string.
  213.         /// </summary>
  214.         /// <param name="encoding">The encoding we should use for getting bytes.</param>
  215.         /// <param name="format">The messages format.</param>
  216.         /// <param name="replacements">Replacement data.</param>
  217.         public static byte[] Message(Encoding encoding, string format, params object[] replacements)
  218.         {
  219.             string message = String.Format(format, replacements);
  220.  
  221.             byte[] bytes = encoding.GetBytes(message);
  222.  
  223.             return bytes;
  224.         }
  225.  
  226.         /// <summary>
  227.         /// Convenience method for sending and flushing data to stream.
  228.         /// </summary>
  229.         /// <param name="tunnel">The stream that we will be sending to.</param>
  230.         /// <param name="message">The message that we are about to send.</param>
  231.         public static void Respond(NetworkStream tunnel, byte[] message)
  232.         {
  233.             tunnel.Write(message, 0, message.Length);
  234.             tunnel.Flush();
  235.         }
  236.  
  237.         /// <summary>
  238.         /// Convenience method for logging information to console.
  239.         /// </summary>
  240.         /// <param name="format">The messages format.</param>
  241.         /// <param name="replacements">Replacement data.</param>
  242.         public static void Log(string format, params object[] replacements)
  243.         {
  244.             // Date+time.
  245.             string date = String.Format("[{0}]", DateTime.Now.ToString("O"));
  246.  
  247.             // Passed message.
  248.             string message = String.Format(format, replacements);
  249.  
  250.             // Grouped.
  251.             string[] messageParts = new string[] { date, message };
  252.  
  253.             // Formatted.
  254.             string log = String.Join(" ", messageParts);
  255.  
  256.             Console.WriteLine(log);
  257.         }
  258.     }
  259. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement