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); }
private void StartReceiveLoop() { testRemoteSocketState.OnNetworkAction = ReceiveLoop; Networking.GetData(testRemoteSocketState); }
private TcpListener StartTestServer(int port) { TcpListener listener = Networking.StartServer(OnNewClient, port); return(listener); }
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; }
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; }
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()); }
public void TestSendNullMessage() { NetworkTestHelper.SetupSingleConnectionTest(out testListener, out testLocalSocketState, out testRemoteSocketState); //Sending null value, should causes a Error in the RemoteState Assert.IsFalse(Networking.Send(testRemoteSocketState.TheSocket, null)); }
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(); }