예제 #1
0
        public void TestChangeOnNetworkAction(bool clientSide)
        {
            SetupTestConnections(clientSide, out testListener, out testLocalSocketState, out testRemoteSocketState, 2120);

            int firstCalledCount  = 0;
            int secondCalledCount = 0;

            // This is an example of a nested method (just another way to make a quick delegate)
            void firstOnNetworkAction(SocketState state)
            {
                if (state.ErrorOccured)
                {
                    return;
                }
                firstCalledCount++;
                state.OnNetworkAction = secondOnNetworkAction;
                Networking.GetData(testLocalSocketState);
            }

            void secondOnNetworkAction(SocketState state)
            {
                secondCalledCount++;
            }

            // Change the OnNetworkAction after the first invokation
            testLocalSocketState.OnNetworkAction = firstOnNetworkAction;

            Networking.Send(testRemoteSocketState.TheSocket, "a");
            Networking.GetData(testLocalSocketState);
            NetworkTestHelper.WaitForOrTimeout(() => firstCalledCount == 1, NetworkTestHelper.timeout);

            Networking.Send(testRemoteSocketState.TheSocket, "a");
            NetworkTestHelper.WaitForOrTimeout(() => secondCalledCount == 1, NetworkTestHelper.timeout);

            Assert.AreEqual(1, firstCalledCount);
            Assert.AreEqual(1, secondCalledCount);
        }
예제 #2
0
        public void GetDataErrorCatching(bool clientSide)
        {
            SetupTestConnections(
                clientSide,
                out testListener,
                out testRemoteSocketState,
                out testLocalSocketState, 2380);

            string data = "";

            void ProcessMessages(SocketState s)
            {
                testRemoteSocketState = s;

                if (s.ErrorOccured)
                {
                    return;
                }

                data += s.GetData() + " ";
                s.RemoveData(0, s.GetData().Length);
            }

            testRemoteSocketState.OnNetworkAction = ProcessMessages;
            bool firstSent;
            bool secondSent;

            firstSent  = Networking.Send(testLocalSocketState.TheSocket, "HelloThere");
            secondSent = Networking.Send(testLocalSocketState.TheSocket, "Pan");

            testRemoteSocketState.TheSocket.Close();
            Networking.GetData(testRemoteSocketState);
            NetworkTestHelper.WaitForOrTimeout(() => false, 3000);

            Assert.IsTrue(testRemoteSocketState.ErrorOccured);
        }
예제 #3
0
        public void TestReceiveHugeMessage(bool clientSide)
        {
            SetupTestConnections(clientSide, out testListener, out testLocalSocketState, out testRemoteSocketState, 2123);

            testLocalSocketState.OnNetworkAction = (x) => {
                if (x.ErrorOccured)
                {
                    return;
                }
                Networking.GetData(x);
            };

            Networking.GetData(testLocalSocketState);

            StringBuilder message = new StringBuilder();

            message.Append('a', (int)(SocketState.BufferSize * 7.5));

            Networking.Send(testRemoteSocketState.TheSocket, message.ToString());

            NetworkTestHelper.WaitForOrTimeout(() => testLocalSocketState.GetData().Length == message.Length, NetworkTestHelper.timeout);

            Assert.AreEqual(message.ToString(), testLocalSocketState.GetData());
        }
예제 #4
0
        public void TestDelayedSends(bool clientSide)
        {
            SetupTestConnections(clientSide, out testListener, out testLocalSocketState, out testRemoteSocketState, 2118);

            // Set the action to do nothing
            testLocalSocketState.OnNetworkAction  = x => { };
            testRemoteSocketState.OnNetworkAction = x => { };

            Networking.Send(testLocalSocketState.TheSocket, "a");
            Networking.GetData(testRemoteSocketState);
            // Note that waiting for data like this is *NOT* how the networking library is
            // intended to be used. This is only for testing purposes.
            // Normally, you would provide an OnNetworkAction that handles the data.
            NetworkTestHelper.WaitForOrTimeout(() => testRemoteSocketState.GetData().Length > 0, NetworkTestHelper.timeout);

            Networking.Send(testLocalSocketState.TheSocket, "b");
            Networking.GetData(testRemoteSocketState);
            // Note that waiting for data like this is *NOT* how the networking library is
            // intended to be used. This is only for testing purposes.
            // Normally, you would provide an OnNetworkAction that handles the data.
            NetworkTestHelper.WaitForOrTimeout(() => testRemoteSocketState.GetData().Length > 1, NetworkTestHelper.timeout);

            Assert.AreEqual("ab", testRemoteSocketState.GetData());
        }
예제 #5
0
        public void TestRapidReceive(bool clientSide)
        {
            SetupTestConnections(clientSide);

            testLocalSocketState.OnNetworkAction = (x) =>
            {
                if (x.ErrorOccured)
                {
                    return;
                }
                Networking.GetData(x);
            };

            Networking.GetData(testLocalSocketState);

            for (int i = 0; i < 10000; i++)
            {
                char c = (char)('a' + (i % 26));
                Networking.Send(testRemoteSocketState.TheSocket, "" + c);
            }


            WaitForOrTimeout(() => testLocalSocketState.GetData().Length == 10000, timeout);

            // Reconstruct the original message outside the send loop
            // to (in theory) make the send operations happen more rapidly.
            StringBuilder message = new StringBuilder();

            for (int i = 0; i < 10000; i++)
            {
                char c = (char)('a' + (i % 26));
                message.Append(c);
            }

            Assert.AreEqual(message.ToString(), testLocalSocketState.GetData());
        }
예제 #6
0
        public void TestTwoServers()
        {
            SocketState server2          = null;
            SocketState client2          = null;
            bool        server2Connected = false;
            bool        receive1Called   = false;
            bool        receive2Called   = false;
            string      client1Message   = "";
            string      client2Message   = "";
            string      server1Message   = "";
            string      server2Message   = "";

            void Server2OnConnect(SocketState s)
            {
                if (s.ErrorOccured)
                {
                    return;
                }
                server2Connected        = true;
                server2                 = s;
                server2.OnNetworkAction = Server2OnReceive;
            }

            void Client2OnConnect(SocketState s)
            {
                if (s.ErrorOccured)
                {
                    return;
                }
                client2 = s;
            }

            void Server1OnReceive(SocketState s)
            {
                if (s.ErrorOccured)
                {
                    return;
                }
                receive1Called = true;
                server1Message = s.GetData();
            }

            void Server2OnReceive(SocketState s)
            {
                if (s.ErrorOccured)
                {
                    return;
                }
                receive2Called = true;
                server2Message = s.GetData();
            }

            void Client1OnReceive(SocketState s)
            {
                if (s.ErrorOccured)
                {
                    return;
                }
                receive1Called = true;
                client1Message = s.GetData();
            }

            void Client2OnReceive(SocketState s)
            {
                if (s.ErrorOccured)
                {
                    return;
                }
                receive2Called = true;
                client2Message = s.GetData();
            }

            // setup first server and client using the normal helper
            SetupTestConnections(false);
            testLocalSocketState.OnNetworkAction = Server1OnReceive;

            // setup second server and client
            TcpListener listener2 = Networking.StartServer(Server2OnConnect, 2222);

            Networking.ConnectToServer(Client2OnConnect, "localhost", 2222);

            // wait for the second pair to connect
            WaitForOrTimeout(() => server2 != null && client2 != null, timeout);

            // Receive on server1
            Networking.GetData(testLocalSocketState);
            // Receive on server2
            Networking.GetData(server2);

            // Receive on client1
            testRemoteSocketState.OnNetworkAction = Client1OnReceive;
            Networking.GetData(testRemoteSocketState);
            // Receive on client2
            client2.OnNetworkAction = Client2OnReceive;
            Networking.GetData(client2);

            // Send from client1 to server1
            Networking.Send(testRemoteSocketState.TheSocket, "a");

            // Send from client2 to server2
            Networking.Send(client2.TheSocket, "b");

            // Send from server1 to client1
            Networking.Send(testLocalSocketState.TheSocket, "c");

            // Send from server2to client2
            Networking.Send(server2.TheSocket, "d");

            WaitForOrTimeout(() => server2Connected && receive1Called && receive2Called, timeout);

            Assert.IsTrue(server2Connected);
            Assert.IsTrue(receive1Called);
            Assert.IsTrue(receive2Called);
            Assert.AreEqual("a", server1Message);
            Assert.AreEqual("b", server2Message);
            Assert.AreEqual("c", client1Message);
            Assert.AreEqual("d", client2Message);
        }
예제 #7
0
 private void StartReceiveLoop()
 {
     testRemoteSocketState.OnNetworkAction = ReceiveLoop;
     Networking.GetData(testRemoteSocketState);
 }
예제 #8
0
        private void GameClients(
            out Dictionary <long, StringBuilder> clientSentMessages,
            out Dictionary <long, StringBuilder> clientReceivedMessages,
            out Dictionary <long, SocketState> clientSockets)
        {
            object clientConnectionsLock = new object();
            //Dictionary<long, SocketState> clientSocketStates = new Dictionary<long, SocketState>();
            Dictionary <long, StringBuilder> sentMessages     = new Dictionary <long, StringBuilder>();
            Dictionary <long, StringBuilder> receivedMessages = new Dictionary <long, StringBuilder>();
            Dictionary <long, SocketState>   sockets          = new Dictionary <long, SocketState>();
            Dictionary <long, Random>        randoms          = new Dictionary <long, Random>();
            Dictionary <long, long>          clientIDs        = new Dictionary <long, long>();
            Random rand = new Random(0);


            // Local function to serve as a callMe delegate
            void clientFirstContact(SocketState state)
            {
                if (state.ErrorOccured)
                {
                    return;
                }
                // Start a receive loop from the server
                state.OnNetworkAction = handleMessage;
                Networking.GetData(state);
            }

            // Local function to serve as a callMe delegate
            // Receive loop for the client that simualtes "processing" a message by
            // looking for a newline separator
            void handleMessage(SocketState state)
            {
                if (state.ErrorOccured)
                {
                    return;
                }
                lock (clientConnectionsLock)
                {
                    // If this is the first message, save the per-connection state for validating the test
                    if (!clientIDs.ContainsKey(state.ID))
                    {
                        // first message contains ID
                        clientIDs[state.ID] = int.Parse(state.GetData().Substring(0, state.GetData().IndexOf("\n") + 1));

                        sentMessages[clientIDs[state.ID]]     = new StringBuilder();
                        receivedMessages[clientIDs[state.ID]] = new StringBuilder();
                        sockets[clientIDs[state.ID]]          = state;
                        randoms[clientIDs[state.ID]]          = new Random((int)clientIDs[state.ID]);
                    }
                }


                StringBuilder rcv, sent;
                Random        rnd;

                lock (clientConnectionsLock)
                {
                    rcv  = receivedMessages[clientIDs[state.ID]];
                    sent = sentMessages[clientIDs[state.ID]];
                    rnd  = randoms[clientIDs[state.ID]];
                }

                ProcessMessage(state, rcv);

                // Decide if we will disconnect or not (1% chance)
                bool disconnect = rnd.Next(100) == 0;

                // Reply to the server about half of the time
                if (!disconnect && rnd.Next(2) == 0)
                {
                    StringBuilder reply = new StringBuilder();
                    for (int i = 0; i < rand.Next(10); i++)
                    {
                        reply.Append((char)('a' + rand.Next(26)));
                    }
                    reply.Append("\n");
                    sent.Append(reply);
                    Networking.Send(state.TheSocket, reply.ToString());
                }

                // Continue the receive loop or disconnect
                if (disconnect)
                {
                    state.TheSocket.Shutdown(SocketShutdown.Both);
                }
                else
                {
                    Networking.GetData(state);
                }
            }

            // Start a stopwatch to simulate clients connecting and disconnecting over time
            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            watch = new System.Diagnostics.Stopwatch();
            watch.Start();

            // 75 opportunities over time for clients to connect
            for (int i = 0; i < 75; i++)
            {
                // Connect 1 - 3 clients
                int numClients = 1 + rand.Next(3);
                for (int j = 0; j < numClients; j++)
                {
                    Networking.ConnectToServer(clientFirstContact, "localhost", 2112);
                }

                while (watch.ElapsedMilliseconds < 30)
                { /* just waiting */
                }

                watch.Restart();
            }

            clientSentMessages     = sentMessages;
            clientReceivedMessages = receivedMessages;
            clientSockets          = sockets;
        }
예제 #9
0
        private void GameServer(
            out Dictionary <long, StringBuilder> serverSentMessages,
            out Dictionary <long, StringBuilder> serverReceivedMessages)
        {
            object serverConnectionsLock = new object();
            Dictionary <long, SocketState>   serverSocketStates = new Dictionary <long, SocketState>();
            Dictionary <long, StringBuilder> sentMessages       = new Dictionary <long, StringBuilder>();
            Dictionary <long, StringBuilder> receivedMessages   = new Dictionary <long, StringBuilder>();
            Random rand = new Random(0);

            // Local function to serve as a callMe delegate
            void serverFirstContact(SocketState state)
            {
                if (state.ErrorOccured)
                {
                    return;
                }
                // Save the socket state so we can broadcast to all clients
                // Also save the rest of the per-connection state for validating the test
                lock (serverConnectionsLock)
                {
                    // Use one of the stringbuilder lists as a unique socket ID
                    // since they will strictly grow (the SocketState lists will grow and shrink)
                    //state.uid = sentMessages.Count;

                    sentMessages[state.ID]       = new StringBuilder();
                    receivedMessages[state.ID]   = new StringBuilder();
                    serverSocketStates[state.ID] = state;

                    // send the client's ID
                    // important to do this inside the lock so the broadcast loop doesn't
                    // run before sending the client's ID
                    sentMessages[state.ID].Append("" + state.ID + "\n");
                    Networking.Send(state.TheSocket, "" + state.ID + "\n");
                }

                // Start a receive loop from the client
                state.OnNetworkAction = removeMessage;
                Networking.GetData(state);
            }

            // Local function to serve as a callMe delegate
            // Receive loop for the server that just removes and saves the client's messages
            void removeMessage(SocketState state)
            {
                if (state.ErrorOccured)
                {
                    return;
                }
                StringBuilder rcv;

                lock (serverConnectionsLock)
                {
                    rcv = receivedMessages[state.ID];
                }

                rcv.Append(state.GetData());
                state.RemoveData(0, state.GetData().Length);
                Networking.GetData(state);
            }

            testListener = Networking.StartServer(serverFirstContact, 2112);

            // Start a stopwatch to simulate a game server's tick-rate
            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            watch = new System.Diagnostics.Stopwatch();
            watch.Start();

            int nextChar = 0;

            // Run for 150 frames
            for (int frame = 0; frame < 150; frame++)
            {
                // Create several messages ranging in size between 0x - 0.5x the buffer size,
                StringBuilder messages = new StringBuilder();
                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < rand.Next((int)(SocketState.BufferSize * 0.5)); j++)
                    {
                        messages.Append((char)('a' + (nextChar++ % 26)));
                    }

                    // Newline separator indicates end of object
                    messages.Append("\n");
                }

                lock (serverConnectionsLock)
                {
                    foreach (StringBuilder sb in sentMessages.Values)
                    {
                        sb.Append(messages);
                    }

                    foreach (SocketState ss in serverSocketStates.Values)
                    {
                        if (ss.TheSocket.Connected)
                        {
                            Networking.Send(ss.TheSocket, messages.ToString());
                        }
                    }
                }

                // Simulate slow-ish server that gives the clients enough time to receive
                // between frames so that we can assume that everything sent is also received
                while (watch.ElapsedMilliseconds < 30)
                { /* just waiting */
                }

                watch.Restart();
            } // end frame loop

            serverSentMessages     = sentMessages;
            serverReceivedMessages = receivedMessages;
        }
예제 #10
0
        public void TestSimulateClientAndServer()
        {
            // For this test, we will use testRemoteSocketState as the server's SocketState
            // and testLocalSocketState as the client's SocketState

            Random        rand           = new Random(0);
            StringBuilder serverReceived = new StringBuilder();
            StringBuilder clientReceived = new StringBuilder();
            StringBuilder clientSent     = new StringBuilder();

            // Local function to serve as a callMe delegate
            void serverFirstContact(SocketState state)
            {
                if (state.ErrorOccured)
                {
                    return;
                }
                // Save the socket state globally so that the Cleanup method can close it
                testRemoteSocketState = state;

                // Start a receive loop from the client
                state.OnNetworkAction = removeMessage;
                Networking.GetData(state);
            }

            // Local function to serve as a callMe delegate
            // Receive loop for the server that just removes and saves the client's messages
            void removeMessage(SocketState state)
            {
                if (state.ErrorOccured)
                {
                    return;
                }
                serverReceived.Append(state.GetData());
                state.RemoveData(0, state.GetData().Length);
                Networking.GetData(state);
            }

            // Local function to serve as a callMe delegate
            void clientFirstContact(SocketState state)
            {
                if (state.ErrorOccured)
                {
                    return;
                }
                // Save the socket state globally so that the Cleanup method can close it
                testLocalSocketState = state;

                // Start a receive loop from the server
                state.OnNetworkAction = handleMessage;
                Networking.GetData(state);
            }

            // Local function to serve as a callMe delegate
            // Receive loop for the client that simualtes "processing" a message by
            // looking for a newline separator
            void handleMessage(SocketState state)
            {
                if (state.ErrorOccured)
                {
                    return;
                }
                ProcessMessage(state, clientReceived);

                // Reply to the server about half of the time
                if (rand.Next(2) == 0)
                {
                    StringBuilder reply = new StringBuilder();
                    for (int i = 0; i < rand.Next(10); i++)
                    {
                        reply.Append((char)('a' + rand.Next(26)));
                    }
                    reply.Append("\n");
                    clientSent.Append(reply);
                    Networking.Send(state.TheSocket, reply.ToString());
                }

                // Continue the receive loop
                Networking.GetData(state);
            }

            // Start the listener
            testListener = Networking.StartServer(serverFirstContact, 2112);
            // Start the client
            Networking.ConnectToServer(clientFirstContact, "localhost", 2112);
            // Wait for both sides to connect
            WaitForOrTimeout(() => testLocalSocketState != null && testRemoteSocketState != null, timeout);

            // Run the server loop
            StringBuilder serverSent = SingleClientServerLoop();

            WaitForOrTimeout(() => clientReceived.Length == serverSent.Length, timeout);
            WaitForOrTimeout(() => clientSent.Length == serverReceived.Length, timeout);

            Assert.AreEqual(clientReceived.ToString(), serverSent.ToString());
            Assert.AreEqual(clientSent.ToString(), serverReceived.ToString());
        }
예제 #11
0
        public void TestMyOwn()
        {
            // List to represents connections
            List <SocketState> server = new List <SocketState>();

            void SaveServer(SocketState s)
            {
                lock (this)
                {
                    server.Add(s);
                }
            }

            //Two clients
            SocketState client_1 = null;

            void SaveClient_1(SocketState s)
            {
                client_1 = s;
            }

            SocketState client_2 = null;

            void SaveClient_2(SocketState s)
            {
                client_2 = s;
            }

            // Starting a server
            TcpListener listener = Networking.StartServer(SaveServer, 2112);

            // Client1 Connect to the server
            Networking.ConnectToServer(SaveClient_1, "localhost", 2112);

            // Client2 Connect to the server
            Networking.ConnectToServer(SaveClient_2, "localhost", 2112);

            // Make sure this line is what you want to it behave
            NetworkTestHelper.WaitForOrTimeout(() => (client_2 != null) && (client_1 != null) && (server.Count == 2), NetworkTestHelper.timeout);

            // Set the action to do nothing
            foreach (SocketState state in server)
            {
                state.OnNetworkAction = x => { };
            }

            client_1.OnNetworkAction = x => { };
            client_2.OnNetworkAction = x => { };

            foreach (SocketState state in server)
            {
                Networking.SendAndClose(state.TheSocket, "a");
            }

            Networking.GetData(client_1);
            Networking.GetData(client_2);


            // Note that waiting for data like this is *NOT* how the networking library is
            // intended to be used. This is only for testing purposes.
            // Normally, you would provide an OnNetworkAction that handles the data.
            NetworkTestHelper.WaitForOrTimeout(() => client_1.GetData().Length > 0 && client_2.GetData().Length > 0, NetworkTestHelper.timeout);

            Assert.AreEqual("a", client_1.GetData());
            Assert.AreEqual("a", client_2.GetData());

            //Make sure everything close and stop properly
            listener.Stop();
            foreach (SocketState state in server)
            {
                state.TheSocket.Close();
            }
            client_1.TheSocket.Close();
            client_2.TheSocket.Close();
        }