Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Diagnostics;
- using System.Net;
- using System.Net.Sockets;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Text;
- namespace SpeedServer
- {
- class Program
- {
- private static int _messageLength = 5;
- private static Stopwatch _tcpTimer = new Stopwatch();
- private static Stopwatch _udpTimer = new Stopwatch();
- static async Task Main(string[] args)
- {
- var ipString = "127.0.0.1";
- Task udpTask;
- Task tcpTask;
- using (var tokenSource = new CancellationTokenSource())
- {
- var token = tokenSource.Token;
- var udpPortNumber = SetupUdpPortNumber();
- var tcpPortNumber = SetupTcpPortNumber();
- var tcpServer = new TcpListener(IPAddress.Parse(ipString), tcpPortNumber);
- tcpServer.Start();
- Console.WriteLine("Tcp server started");
- tcpTask = Task.Run(() => ProcessTcpClients(tcpServer, token), token);
- udpTask = Task.Run(async () =>
- {
- using (var udpClient = new UdpClient(udpPortNumber))
- {
- while (!token.IsCancellationRequested)
- {
- if (udpClient.Available <= 0)
- {
- continue;
- }
- _udpTimer.Restart();
- var data = await ReceiveUdpData(udpClient);
- var udpMessageLength = data.Length;
- Console.WriteLine($"Udp Message: {string.Join(", ", data)}");
- var kilobits = GetBitsAmount(udpMessageLength) / 1000f;
- var totalSeconds = _udpTimer.Elapsed.TotalSeconds;
- Console.WriteLine($"Thread UDP: received {kilobits}kb in time {totalSeconds}sec with the speed {kilobits / totalSeconds:F3}kb/sec");
- }
- }
- Console.WriteLine("Cancellation token set");
- }, token);
- while (!Console.KeyAvailable && Console.ReadKey().Key != ConsoleKey.Escape) { };
- tokenSource.Cancel();
- }
- Console.WriteLine("Awaiting tcp");
- await tcpTask;
- Console.WriteLine("Awaiting udp");
- await udpTask;
- //StopServers(tcpServer, udpServer);
- }
- private static int SetupUdpPortNumber()
- {
- Console.WriteLine("Send nudes through UDP");
- var readLine = Console.ReadLine();
- readLine = string.IsNullOrEmpty(readLine) ? "333" : readLine;
- var udpPortNumber = int.Parse(readLine);
- Console.WriteLine(udpPortNumber);
- if (udpPortNumber == 333)
- {
- Console.WriteLine("Using default port 333");
- }
- return udpPortNumber;
- }
- private static int SetupTcpPortNumber()
- {
- Console.WriteLine("Send nudes through TCP");
- var readLine = Console.ReadLine();
- readLine = string.IsNullOrEmpty(readLine) ? "444" : readLine;
- var tcpPortNumber = int.Parse(readLine);
- if (tcpPortNumber == 444)
- {
- Console.WriteLine("Using default port 444");
- }
- return tcpPortNumber;
- }
- private static void StopServers(TcpListener tcpServer, UdpClient udpServer)
- {
- tcpServer.Stop();
- udpServer.Close();
- udpServer.Dispose();
- }
- private static async Task<byte[]> ReceiveUdpData(UdpClient udpClient)
- {
- return (await udpClient.ReceiveAsync()).Buffer;
- }
- private static async Task ProcessTcpClients(TcpListener tcpListener, CancellationToken token)
- {
- var busy = false;
- while (!token.IsCancellationRequested)
- {
- //Console.WriteLine("Waiting for client");
- if (tcpListener.Pending())
- {
- var client = await tcpListener.AcceptTcpClientAsync();
- Console.WriteLine("Client connected");
- if (await RejectIfBusyAsync(busy, client))
- {
- Console.WriteLine("Client rejected");
- continue;
- }
- Console.WriteLine("Client accepted");
- busy = true;
- #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
- Task.Run(async () =>
- {
- try
- {
- await HandleClient(client, token);
- }
- finally
- {
- busy = false;
- client.Close();
- }
- },
- token);
- }
- }
- }
- private static async Task<bool> RejectIfBusyAsync(bool busy, TcpClient client)
- {
- if (!busy)
- {
- return false;
- }
- using var stream = client.GetStream();
- var busyBytes = Encoding.ASCII.GetBytes("BUSY");
- await stream.WriteAsync(busyBytes);
- return true;
- }
- private static async Task HandleClient(TcpClient client, CancellationToken token)
- {
- Console.WriteLine("Getting stream");
- using var stream = client.GetStream();
- Console.WriteLine("Got stream");
- _messageLength = await SetupMessageLengthAsync(client, stream, token);
- await ReadFromClientStream(client, stream, token);
- }
- private static async Task<int> SetupMessageLengthAsync(TcpClient client, NetworkStream stream, CancellationToken token)
- {
- var messageFormat = "SIZE:XYZ";
- var sizeMessageLength = messageFormat.Length;
- var buffer = new byte[sizeMessageLength];
- try
- {
- Console.WriteLine("Reading");
- await stream.ReadAsync(buffer, 0, sizeMessageLength, token);
- Console.WriteLine("Finished reading");
- var messageString = Encoding.ASCII.GetString(buffer);
- return int.Parse(messageString.Substring(5, 3));
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- stream.Dispose();
- client.Dispose();
- return -1;
- }
- }
- private static async Task ReadFromClientStream(TcpClient client, NetworkStream stream, CancellationToken token)
- {
- var currentBytesRead = 0;
- do
- {
- var totalBytesRead = 0;
- var buffer = new byte[_messageLength];
- try
- {
- _tcpTimer.Restart();
- do
- {
- Console.WriteLine("Reading");
- currentBytesRead = await stream.ReadAsync(buffer, totalBytesRead, _messageLength - totalBytesRead, token);
- totalBytesRead += currentBytesRead;
- if (CloseRequested(buffer))
- {
- Cleanup(client, stream);
- return;
- }
- } while (totalBytesRead < _messageLength && currentBytesRead != 0);
- Console.WriteLine("Finished reading");
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- Cleanup(client, stream);
- return;
- }
- Console.WriteLine($"Message: {string.Join(", ", buffer)}");
- var kilobits = GetBitsAmount(_messageLength) / 1000f;
- var totalSeconds = _tcpTimer.Elapsed.TotalSeconds;
- Console.WriteLine($"Thread TCP: received {kilobits}kb in time {totalSeconds}sec with the speed {kilobits / totalSeconds:F3}kb/sec");
- } while (currentBytesRead != 0 && !token.IsCancellationRequested);
- }
- private static int GetBitsAmount(int messageLength)
- {
- return (messageLength * 8);
- }
- private static void Cleanup(TcpClient client, NetworkStream stream)
- {
- client.Dispose();
- stream.Dispose();
- }
- private static bool CloseRequested(byte[] buffer)
- {
- var msgAscii = Encoding.ASCII.GetString(buffer);
- var closeRequested = msgAscii.Contains("FINE");
- if (closeRequested)
- {
- Console.WriteLine("Close requested by client");
- }
- return closeRequested;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement