示例#1
0
文件: Client.cs 项目: I0xAF/EasyTcp
        static void Main(string[] args)
        {
            EasyTcpClient client = new EasyTcpClient(System.Reflection.Assembly.GetExecutingAssembly());

            client.OnConnected += (sender, tcp) =>
            {
                Console.WriteLine("Client successfuly connected!");
                client.Send(new Packet(BytesTransformation.TransformIt("Test String", "Test String2", 1337, true, 412.214, 4124u), "Some packet"));
            };
            client.OnDisconnect += (sender, tcp) =>
            {
                Console.WriteLine("Client disconnected!");
            };
            client.OnError += (sender, error) =>
            {
                Console.WriteLine($"{error.Message}\n{error.StackTrace}");
            };
            client.DataReceived += (sender, msg) =>
            {
                Console.WriteLine($"PacketType: {msg.GetPacket.PacketType}");
                client.PacketHandler(msg, false);
            };
            if (!client.Connect("127.0.0.1", 6124, TimeSpan.FromSeconds(15)))
            {
                Console.WriteLine("Connection aborted. Timeout!");
            }
            Console.ReadLine();
            Task.Delay(-1).Wait();
        }
示例#2
0
        public async Task Stream1() //Client -> -(Stream)> Server     (Client sends message to server)
        {
            ushort port = TestHelper.GetPort();

            using var server = new EasyTcpServer();
            server.Start(port);

            using var client = new EasyTcpClient();
            Assert.IsTrue(client.Connect(IPAddress.Any, port));

            string testData = "123", data = "";

            server.OnDataReceiveAsync += async(sender, message) =>  //Receive stream from client
            {
                await using var stream = new MemoryStream();
                await message.ReceiveStreamAsync(stream);

                data = Encoding.UTF8.GetString(stream.ToArray());
            };

            //Send stream to server
            await using var dataStream = new MemoryStream(Encoding.UTF8.GetBytes(testData));
            client.Send("Stream");
            await client.SendStreamAsync(dataStream);

            TestHelper.WaitWhileTrue(() => data == "");
            Assert.AreEqual(testData, data);
        }
示例#3
0
        public void Start(ushort port)
        {
            EasyTcpClient selectedClient = null;

            using var server = new EasyTcpServer().Start(port);

            server.OnError       += (s, exception) => Console.WriteLine($"Server error: {exception.Message}");
            server.OnDataReceive += (s, message) =>
            {
                if (selectedClient == message.Client)
                {
                    Console.WriteLine(message.Decompress().ToString());
                }
            };

            while (true)
            {
                string command = Console.ReadLine();
                if (string.IsNullOrWhiteSpace(command))
                {
                    continue;
                }

                var args = command.Split(' ');
                command = args[0];

                ExecuteCommand(command, args.Skip(1).ToArray(), server, ref selectedClient);
            }
        }
        public static void Connect()
        {
            var client = new EasyTcpClient();

            if (!client.Connect(IPAddress.Loopback, Port))
            {
                return;
            }

            var list = new PacketList <Message>
            {
                EasyTcpPacket.To <Message>("Message1"),
                EasyTcpPacket.To <Message>("Message2"),
                EasyTcpPacket.To <Message>("Message3")
            };

            client.Send(list); // Send list

            // Message also implements IEasyTcpPacket
            // So we can use all functions on message as example
            // This is how we create a new message with as content a string
            // The EasyTcpPacket.To can be used on all packets, but not all packets support being created from a string
            // Our list for example wouldn't work when created from a string
            var message = EasyTcpPacket.To <Message>("S_T_R_I_N_G");

            message.Compress(); // Compress message
        }
示例#5
0
        public static void Connect()
        {
            using var client = new EasyTcpClient();
            if (!client.Connect("127.0.0.1", Port))
            {
                return;
            }

            // Trigger action
            client.SendAction("ReceiveStream");

            // Send large array
            // Length of stream is prefixed by default (long as byte[8])
            var stream = new MemoryStream(new byte[100000]);

            client.SendStream(stream);

            // Send stream without length prefix
            var stream2 = new MemoryStream(new byte[10000]);

            client.SendStream(stream2, sendLengthPrefix: false);
            Console.ReadLine();

            // Writing / reading the base stream is also possible
            var baseStream = client.Protocol.GetStream(client);
        }
示例#6
0
        public void Stream1() //Client -> -(Stream)> Server     (Client sends message to server)
        {
            ushort port = TestHelper.GetPort();

            using var server = new EasyTcpServer().Start(port);

            using var client = new EasyTcpClient();
            Assert.IsTrue(client.Connect(IPAddress.Any, port));

            string testData = "123", data = null;

            server.OnDataReceive += (sender, message) => //Receive stream from client
            {
                using var stream = new MemoryStream();
                message.ReceiveStream(stream, compression: true);
                data = Encoding.UTF8.GetString(stream.ToArray());
            };

            //Send stream to server
            using var dataStream = new MemoryStream(Encoding.UTF8.GetBytes(testData));
            client.Send("Stream");
            client.SendStream(dataStream, compression: true);

            TestHelper.WaitWhileTrue(() => data == null);
            Assert.AreEqual(testData, data);
        }
示例#7
0
        public async Task Connect1()
        {
            using var client = new EasyTcpClient();
            bool isConnected = await client.ConnectAsync(IPAddress.Any, _port);

            Assert.IsTrue(isConnected);
        }
示例#8
0
        public static void Connect()
        {
            var client = new EasyTcpClient();

            if (!client.Connect("127.0.0.1", Port))
            {
                return;
            }

            // All actions are send as an int, this is the action id of the "ECHO" action.
            // Integers can also be used as action codes. However this is not very readable, so when using integers enums are recommend!
            // Because everything is send as an int collisions are possible. (The algorithm used is named djb2a [http://www.cse.yorku.ca/~oz/hash.html])
            // This is no problem because this is very rare, however keep it in mind!
            // Try for example these two: haggadot & loathsomenesses
            int actionCode = "ECHO".ToActionCode();

            // Execute the "ECHO" action on our echo server
            client.SendAction("ECHO", "Hello me!");

            // Execute the "BROADCAST" action on our echo server
            client.SendAction("BROADCAST", "Hello everyone!");

            // Get the reply from our message
            var message = client.SendActionAndGetReply(actionCode, "Hello me!");
        }
示例#9
0
        public static void Connect()
        {
            using var client = new EasyTcpClient();

            /* OnConnect event,
             * triggered when client connects to the server
             */
            client.OnConnect += (object sender, EasyTcpClient c) => Console.WriteLine("Client: Connected to server");

            /* OnDisconnect event,
             * triggered when client disconnects from server
             */
            client.OnDisconnect += (object sender, EasyTcpClient c) =>
                                   Console.WriteLine("Client: Disconnected from server");

            /* OnDataReceive event,
             * triggered when client receives any data from the server
             */
            client.OnDataReceive += (object sender, Message message) =>
                                    Console.WriteLine($"Client: Received data, received: {message}");

            /* OnError event,
             * triggered when an unexpected error occurs withing the clients code or in any event
             * error is thrown when ignored
             */
            client.OnError += (object sender, Exception exception) =>
            {
                Console.WriteLine($"Server: Error occured, message: {exception.Message}");
                Environment.Exit(1);
            };
        }
示例#10
0
        /// <summary>
        /// Establish connection with remote host
        /// </summary>
        /// <param name="client"></param>
        /// <param name="endPoint">endPoint of remote host</param>
        /// <param name="socket">base socket for EasyTcpClient, new one is created when null</param>
        /// <returns>determines whether the client connected successfully</returns>
        public static async Task <bool> ConnectAsync(this EasyTcpClient client, EndPoint endPoint, Socket socket = null)
        {
            if (client == null)
            {
                throw new ArgumentException("Could not connect: client is null");
            }
            if (endPoint == null)
            {
                throw new ArgumentException("Could not connect: endpoint is null");
            }
            if (client.BaseSocket != null)
            {
                throw new ArgumentException("Could not connect: client is already connected");
            }

            try
            {
                client.BaseSocket = socket ?? client.Protocol.GetSocket(endPoint.AddressFamily);
                await client.BaseSocket.ConnectAsync(endPoint);

                if (client.BaseSocket.Connected && client.Protocol.OnConnect(client))
                {
                    client.FireOnConnect();
                    return(true);
                }
            }
            catch
            {
                // Ignore exception, dispose (&disconnect) client and return false
            }

            client.Dispose(); // Set socket to null
            return(false);
        }
示例#11
0
        /// <summary>
        /// Handle received data
        /// </summary>
        /// <param name="data">received data, has size of clients buffer</param>
        /// <param name="receivedBytes">amount of received bytes</param>
        /// <param name="client"></param>
        public override async Task DataReceive(byte[] data, int receivedBytes, EasyTcpClient client)
        {
            byte receivedByte = data[0]; // Size of buffer is always 1

            ReceivedBytes.Add(receivedByte);

            // Check delimiter
            if (ReceivedBytes.Count < Delimiter.Length)
            {
                return;
            }

            int receivedBytesLength = ReceivedBytes.Count - Delimiter.Length;

            for (int i = 0; i < Delimiter.Length; i++)
            {
                if (Delimiter[i] != ReceivedBytes[receivedBytesLength + i])
                {
                    return;
                }
            }

            byte[] receivedData = AutoRemoveDelimiter
                ? ReceivedBytes.Take(receivedBytesLength).ToArray() // Remove delimiter from message
                : ReceivedBytes.ToArray();
            await client.DataReceiveHandler(new Message(receivedData, client));

            ReceivedBytes.Clear();
        }
示例#12
0
        public void Stream()
        {
            var    certificate = new X509Certificate2("certificate.pfx", "password");
            ushort port        = TestHelper.GetPort();

            using var server = new EasyTcpServer().UseSsl(certificate).Start(port);

            using var client = new EasyTcpClient().UseSsl("localhost", true);
            Assert.IsTrue(client.Connect(IPAddress.Any, port));

            string testData = "123", data = null;

            server.OnDataReceiveAsync += async(sender, message) =>  //Receive stream from client
            {
                await using var stream = new MemoryStream();
                message.ReceiveStream(stream);
                data = Encoding.UTF8.GetString(stream.ToArray());
            };

            //Send stream to server
            using var dataStream = new MemoryStream(Encoding.UTF8.GetBytes(testData));
            client.Send("Stream");
            client.SendStream(dataStream);

            TestHelper.WaitWhileTrue(() => data == null);
            Assert.AreEqual(testData, data);
        }
示例#13
0
        public static void Run()
        {
            // Create server with logging enabled
            // Write log to console
            using var server      = new EasyTcpServer().UseServerLogging(Console.WriteLine).Start(Port);
            server.OnDataReceive += (s, message) => message.Client.Send("Hello client test!");

            // Create client with logging enabled
            using var client = new EasyTcpClient().UseClientLogging(Console.WriteLine);
            if (!client.Connect("127.0.0.1", Port))
            {
                return;
            }

            client.Send("Hello server!");
            Console.ReadLine();

            /* Custom logging,
             * only log connect/disconnect events
             */
            using var server2 = new EasyTcpServer().UseCustomServerLogging(logMessage =>
            {
                if (logMessage.Type == LoggingType.ClientConnected)
                {
                    Console.WriteLine(logMessage);
                }
                else if (logMessage.Type == LoggingType.ClientDisconnected)
                {
                    Console.WriteLine(logMessage);
                }
            });
        }
        /// <summary>
        /// Send data (byte[][]) to the remote host. Then wait for a reply from the server.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="data">data to send to server</param>
        /// <param name="timeout">maximum time to wait for a reply, if time expired: return null</param>
        /// <returns>received data or null</returns>
        public static async Task <Message> SendAndGetReplyAsync(this EasyTcpClient client, TimeSpan?timeout = null,
                                                                params byte[][] data)
        {
            Message reply = null;

            using var signal = new SemaphoreSlim(0, 1); // Use SemaphoreSlim as async ManualResetEventSlim

            client.DataReceiveHandler = message =>
            {
                reply = message;
                client.ResetDataReceiveHandler();
                // Function is no longer used when signal is disposed, therefore ignore this warning
                // ReSharper disable once AccessToDisposedClosure
                signal.Release();
            };
            client.Send(data);

            await signal.WaitAsync(timeout ?? TimeSpan.FromMilliseconds(DefaultTimeout));

            if (reply == null)
            {
                client.ResetDataReceiveHandler();
            }
            return(reply);
        }
示例#15
0
        public static void Connect()
        {
            var client = new EasyTcpClient();

            if (!client.Connect("127.0.0.1", Port))
            {
                return;
            }

            // Send action
            client.SendAction("ECHO", "Hello me!");
            client.SendAction("BROADCAST", "Hello everyone!");

            // Send action and get reply
            var reply = client.SendActionAndGetReply("ECHO", "Hello me!");

            Console.WriteLine(reply);

            /* All actions are converted to an int(actionCode), this is the actionCode of the "ECHO" action.
             * Integers can also be used as action codes. However this is not very readable.
             * Because everything is send as an int collisions are possible. (The algorithm used is named djb2a [http://www.cse.yorku.ca/~oz/hash.html])
             * This is no problem because this is extremely rare, however keep it in mind!
             */
            int actionCode = "ECHO".ToActionCode();

            Console.WriteLine(actionCode);
            Console.WriteLine(actionCode.IsEqualToAction("ECHO2"));
        }
示例#16
0
        private async void PollServer(object source, ElapsedEventArgs e)
        {
            Console.WriteLine("Polling Server");

            try
            {
                using var client = new EasyTcpClient();
                var pingRecived = client.Connect(_discordSecrets.IpAddress, 25565);
                client.Dispose();

                if (pingRecived != _lastStatusRepo.WasPreviouslyOnline())
                {
                    _lastStatusRepo.SaveIsOnlineStatus(pingRecived);

                    if (pingRecived)
                    {
                        await SendServerOnlineMessage(true);
                    }
                    else
                    {
                        await SendServerOnlineMessage(false);
                    }
                }
            }
            catch (Exception exception)
            {
                Console.WriteLine("Unable to complete command:");
                Console.WriteLine(exception.Message);
            }
        }
示例#17
0
        /// <summary>
        /// Send stream to the remote host
        /// Host can only receive a stream when not listening for incoming messages
        /// </summary>
        /// <param name="client"></param>
        /// <param name="stream">input stream</param>
        /// <param name="compression"></param>
        /// <param name="sendLengthPrefix">determines whether prefix with length of the data is send</param>
        /// <param name="bufferSize"></param>
        /// <exception cref="InvalidDataException">stream is not readable</exception>
        public static async Task SendStreamAsync(this EasyTcpClient client, Stream stream, bool compression = false,
                                                 bool sendLengthPrefix = true,
                                                 int bufferSize        = 1024)
        {
            if (client?.BaseSocket == null)
            {
                throw new Exception("Client is not connected");
            }
            if (!stream.CanRead)
            {
                throw new InvalidDataException("Stream is not readable");
            }

            using var networkStream = client.Protocol.GetStream(client);
            using var dataStream    = compression ? new GZipStream(networkStream, CompressionMode.Decompress) : networkStream;

            if (sendLengthPrefix)
            {
                await dataStream.WriteAsync(BitConverter.GetBytes(stream.Length), 0, 8);
            }

            var buffer = new byte[bufferSize];
            int read;

            while ((read = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
            {
                await dataStream.WriteAsync(buffer, 0, read);
            }
        }
示例#18
0
        public void Connect1()
        {
            using var client = new EasyTcpClient();
            bool isConnected = client.Connect(IPAddress.Any, _port, TimeSpan.FromSeconds(1));

            Assert.IsTrue(isConnected);
        }
示例#19
0
        public void TestLargeArray()
        {
            ushort port = TestHelper.GetPort();

            using var server      = new EasyTcpServer().Start(port);
            server.OnDataReceive += async(sender, message) =>
            {
                var array = await message.ReceiveLargeArrayAsync();

                message.Client.Send(array.Length);
                await message.Client.SendLargeArrayAsync(array);
            };

            byte[] receivedArray = null;

            using var client      = new EasyTcpClient();
            client.OnDataReceive += (sender, message) => receivedArray = message.ReceiveLargeArray();
            Assert.IsTrue(client.Connect(IPAddress.Loopback, port));

            client.Send("first message");

            byte[] largeMessage = new byte[ushort.MaxValue * 10];
            for (int i = 0; i < largeMessage.Length; i++)
            {
                largeMessage[i] = 11;
            }

            client.SendLargeArray(largeMessage);
            TestHelper.WaitWhileTrue(() => receivedArray == null);
            Assert.IsTrue(receivedArray.SequenceEqual(largeMessage));
        }
示例#20
0
        public void Connect2()
        {
            using var client = new EasyTcpClient();
            bool isConnected = client.Connect(IPAddress.Any, _port); //Use default timeout of 5 seconds

            Assert.IsTrue(isConnected);
        }
示例#21
0
        public async Task Connect2()
        {
            using var client = new EasyTcpClient();
            bool isConnected = await client.ConnectAsync("127.0.0.1", _port);

            Assert.IsTrue(isConnected);
        }
示例#22
0
        public void Connect3()
        {
            using var client = new EasyTcpClient();
            bool isConnected = client.Connect("127.0.0.1", _port, TimeSpan.FromSeconds(1));

            Assert.IsTrue(isConnected);
        }
示例#23
0
        /// <summary>
        /// Start listening for incoming data
        /// </summary>
        /// <param name="client"></param>
        public virtual void EnsureDataReceiverIsRunning(EasyTcpClient client)
        {
            if (IsListening)
            {
                return;
            }
            IsListening = true;

            var protocol = (DefaultTcpProtocol)client.Protocol;

            if (protocol.ReceiveBuffer == null)
            {
                protocol.ReceiveBuffer = new SocketAsyncEventArgs {
                    UserToken = client
                };
                protocol.ReceiveBuffer.Completed += (_, ar) => OnReceiveCallback(ar);
            }

            var bufferSize = BufferSize;

            protocol.ReceiveBuffer.SetBuffer(new byte[bufferSize], 0, bufferSize);
            if (!client.BaseSocket.ReceiveAsync(protocol.ReceiveBuffer))
            {
                OnReceiveCallback(protocol.ReceiveBuffer);
            }
        }
示例#24
0
        public void Connect4()
        {
            using var client = new EasyTcpClient();
            bool isConnected = client.Connect("127.0.0.1", _port); //Use default timeout of 5 seconds

            Assert.IsTrue(isConnected);
        }
示例#25
0
        public void OnDataReceive2()
        {
            // Example receiving for the client
            ushort port = TestHelper.GetPort();

            using var server = new EasyTcpServer();
            server.Start(port);

            using var client = new EasyTcpClient();
            Assert.IsTrue(client.Connect(IPAddress.Any, port));

            const string message      = "Hello client!";
            int          receiveCount = 0;

            client.OnDataReceive += (sender, receivedMessage) =>
            {
                //Async lambda, so thread safe increase integer
                if (message.Equals(receivedMessage.ToString()))
                {
                    Interlocked.Increment(ref receiveCount);
                }
                Console.WriteLine($"[{receiveCount}]Received message: {receivedMessage.ToString()}");
            };

            server.SendAll(message);
            server.SendAll(message);

            TestHelper.WaitWhileTrue(() => receiveCount < 2);
            Assert.AreEqual(2, receiveCount);
        }
示例#26
0
        /// <summary>
        /// Send stream to the remote host
        /// </summary>
        /// <param name="client"></param>
        /// <param name="stream">input stream</param>
        /// <param name="compression">compress data using deflate if set to true</param>
        /// <param name="sendLengthPrefix">determines whether prefix with length of the data is send to the remote host</param>
        /// <param name="bufferSize"></param>
        public static void SendStream(this EasyTcpClient client, Stream stream,
                                      bool compression = false, bool sendLengthPrefix = true, int bufferSize = 1024)
        {
            if (client?.BaseSocket == null)
            {
                throw new Exception("Could not send stream: client is not connected");
            }
            if (!stream.CanRead)
            {
                throw new InvalidDataException("Could not send stream: stream is not readable");
            }

            var networkStream = client.Protocol.GetStream(client);
            var dataStream    = compression ? new DeflateStream(networkStream, CompressionMode.Compress, true) : networkStream;

            if (sendLengthPrefix)
            {
                dataStream.Write(BitConverter.GetBytes(stream.Length), 0, 8);
            }

            var buffer = new byte[bufferSize];
            int read;

            while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
            {
                dataStream.Write(buffer, 0, read);
            }

            if (compression)
            {
                dataStream.Dispose();
            }
        }
示例#27
0
        public void Stream2() //Client -> Server -(Stream)> Client     (Client requests stream from server)
        {
            ushort port = TestHelper.GetPort();

            using var server = new EasyTcpServer();
            server.Start(port);

            string testData = "123", data = null;

            using var client = new EasyTcpClient();
            Assert.IsTrue(client.Connect(IPAddress.Any, port));

            server.OnDataReceive += (sender, message) => //Send stream if client requests
            {
                using var dataStream = new MemoryStream(Encoding.UTF8.GetBytes(testData));
                message.Client.Send("Stream");
                message.Client.SendStream(dataStream);
            };

            client.OnDataReceive += (sender, message) => //Receive stream from server
            {
                using var stream = new MemoryStream();
                message.ReceiveStream(stream);
                data = Encoding.UTF8.GetString(stream.ToArray());
            };
            client.Send("GetStream"); //Request stream

            TestHelper.WaitWhileTrue(() => data == null);
            Assert.AreEqual(testData, data);
        }
示例#28
0
        /// <summary>
        /// Function that gets triggered when data a new client connects
        /// </summary>
        /// <param name="ar"></param>
        internal static void OnClientConnect(IAsyncResult ar)
        {
            var server = ar.AsyncState as EasyTcpServer;

            if (server?.BaseSocket == null || !server.IsRunning)
            {
                return;
            }

            try
            {
                var client = new EasyTcpClient(server.BaseSocket.EndAccept(ar));
                client.OnDataReceive += (_, message) => server.FireOnDataReceive(message);
                client.OnDisconnect  += (_, c) => server.FireOnDisconnect(c);
                client.OnError       += (_, exception) => server.FireOnError(exception);

                client.StartListening();
                server.FireOnConnect(client);
                if (client.BaseSocket != null) //Check if user aborted OnConnect with Client.Dispose()
                {
                    lock (server.ConnectedClients) server.ConnectedClients.Add(client);
                }
            }
            catch (Exception ex)
            {
                server.FireOnError(ex);
            }

            server.BaseSocket.BeginAccept(OnClientConnect, server); //Accept next client
        }
示例#29
0
        /// <summary>
        /// Establishes connection with remote host
        /// </summary>
        /// <param name="client"></param>
        /// <param name="endPoint">endPoint of remote host</param>
        /// <param name="timeout">maximum time for connecting with remote host</param>
        /// <param name="socket">socket for EasyTcpClient, new one is create when null</param>
        /// <returns>determines whether the client connected successfully</returns>
        public static bool Connect(this EasyTcpClient client, EndPoint endPoint, TimeSpan?timeout = null,
                                   Socket socket = null)
        {
            if (client == null)
            {
                throw new ArgumentException("Could not connect: client is null");
            }
            if (endPoint == null)
            {
                throw new ArgumentException("Could not connect: endpoint is null");
            }
            if (client.BaseSocket != null)
            {
                throw new ArgumentException("Could not connect: client is still connected");
            }

            try
            {
                client.BaseSocket = socket ?? client.Protocol.GetSocket(endPoint.AddressFamily);
                client.BaseSocket.ConnectAsync(endPoint).Wait(DefaultTimeout);

                if (client.BaseSocket.Connected && client.Protocol.OnConnect(client))
                {
                    client.FireOnConnect();
                    return(true);
                }
            }
            catch
            {
                //Ignore exception, dispose (&disconnect) client and return false
            }

            client.Dispose();
            return(false);
        }
示例#30
0
        public void TestConnectedClients()
        {
            ushort port = TestHelper.GetPort();

            using var server = new EasyTcpServer().Start(port);
            Assert.IsEmpty(server.GetConnectedClients());

            using var client = new EasyTcpClient();
            client.Connect(IPAddress.Loopback, port);
            TestHelper.WaitWhileFalse(() => server.ConnectedClientsCount == 1);
            Assert.AreEqual(1, server.ConnectedClientsCount);

            using var client2 = new EasyTcpClient();
            client2.Connect(IPAddress.Loopback, port);
            TestHelper.WaitWhileFalse(() => server.ConnectedClientsCount == 2);
            Assert.AreEqual(2, server.ConnectedClientsCount);

            client.Dispose();
            TestHelper.WaitWhileTrue(() => server.ConnectedClientsCount == 2);
            Assert.AreEqual(1, server.ConnectedClientsCount);

            client2.Dispose();
            TestHelper.WaitWhileTrue(() => server.ConnectedClientsCount == 1);
            Assert.AreEqual(0, server.ConnectedClientsCount);
        }