/// <summary> /// Takes a SocketState object, state, and initiates a game with the /// server associated with state by sending the name given by the user. /// </summary> private void FirstContact(SocketState state) { if (state.HasError) { // report the error to the user // show error message string errorMessage = "An error occured trying to contact the server"; errorMessage += "\nPlease try to connect again"; ReportNetworkError(errorMessage); // get out of the call loop return; } string name = window.GetUserName(); name += "\n"; // begin "handshake" by sending name Network.Send(state.GetSocket(), name); // Change the action that is taken when a network event occurs. Now when data is received, // the Networking library will invoke ReceiveStartup state.SetNetworkAction(ReceiveStartup); Network.GetData(state); }
/// <summary> /// Takes a SocketState object, state, extracts the player ID and world /// size, updates the network action and waits for more data. /// </summary> private void ReceiveStartup(SocketState state) { if (state.HasError) { // report the error to the user // show error message string errorMessage = "An error occured trying to contact the server"; errorMessage += "\nPlease try to connect again"; ReportNetworkError(errorMessage); // get out of the call loop return; } // get the player ID and world size out of state.sb IEnumerable <string> tokens = GetTokens(state.GetStringBuilder()); List <string> IDAndWorldSize = new List <string>(); foreach (string token in tokens) { IDAndWorldSize.Add(token); // we only want two tokens if (IDAndWorldSize.Count >= 2) { break; } } // see if we actually got out two tokens, should be world size and // player id, if we did, process them and change network action if (IDAndWorldSize.Count == 2) { // remove tokens from StringBuilder should be size of tokens int sizeOfTokensAndNewLines = IDAndWorldSize[0].Length + IDAndWorldSize[1].Length; state.GetStringBuilder().Remove(0, sizeOfTokensAndNewLines); // Update the action to take when network events happen state.SetNetworkAction(ProcessMessage); // create new world theWorld = new World(); window.SetWorld(theWorld); // parse the id and worldsize and set them in our client GetWorldSizeAndID(IDAndWorldSize, out int ID, out int worldSize); //SetPlayerID(ID); SetWorldSize(worldSize); // now that we have a connection, we can start sending controls StartSendingControls(state.GetSocket()); } // Start waiting for data Network.GetData(state); }
public void SocketState_ConstructorTest() { // create a socket using to pass to a SocketState object Network.MakeSocket("localhost", out Socket sock, out IPAddress address); try { SocketState state = new SocketState(sock, -1); //the state should not be reporting an error Assert.IsFalse(state.HasError); // there error messgae should be an empty string Assert.IsTrue(state.ErrorMessage == ""); //the size of the buffer should be 1024 byte[] buffer = state.GetMessageBuffer(); Assert.AreEqual(1024, buffer.Length); // the message buffer should be filled with 0's byte zeroByte = 0x0; for (int i = 0; i < buffer.Length; i++) { Assert.IsTrue(buffer[i] == zeroByte); } // growable string builder which represents the message sent by server // should not contain anything. StringBuilder sb = state.GetStringBuilder(); Assert.IsTrue(sb.ToString() == ""); Assert.AreEqual(0, sb.Length); // the socket returned by GetSocket should be the same instance as // passed to the constructor Assert.AreEqual(sock, state.GetSocket()); // We have not set a network action, but it should still not be null // trying to invoke this action would be bad if it was null and cause // test to fail state.InvokeNetworkAction(state); // ID should be same as what it was set Assert.AreEqual(-1, state.GetID()); } // make sure we close the socket when we are done testing our state finally { sock.Dispose(); } }
/// <summary> /// This method parses the HTTP request sent by the broswer, and serves the appropriate web page. /// </summary> /// <param name="state">The socket state representing the connection with the client</param> private static void ServeHttpRequest(SocketState state) { string request = state.GetStringBuilder().ToString(); // Print it for debugging/examining Console.WriteLine("received http request: " + request); // If the browser requested the server stats if (request.Contains("GET /scores HTTP/1.1")) { string html = MakeHTMLforStats(); Console.WriteLine(html); Network.SendAndClose(state.GetSocket(), httpOkHeader + MakeHTMLforStats()); } // If the browser requested a player else if (request.StartsWith(@"GET /games?player=")) { // maybe split? string playerName = GetRequestParameter(request); string html = MakeHTMLforPlayer(playerName); if (html.Length == 0) { Network.SendAndClose(state.GetSocket(), httpBadHeader + "<h2>the passed in player does not exist</h2>"); } else { Network.SendAndClose(state.GetSocket(), httpOkHeader + html); } } // If the browser requested a game else if (request.StartsWith(@"GET /games?player=")) { string html = MakeHTMLforGame(GetRequestParameter(request)); if (html.Length == 0) { Network.SendAndClose(state.GetSocket(), httpBadHeader + "<h2>the passed in game ID does not exist</h2>"); } else { Network.SendAndClose(state.GetSocket(), httpOkHeader + html); } } // Otherwise, our very simple web server doesn't recognize any other URL else { Network.SendAndClose(state.GetSocket(), httpBadHeader + "<h2>page not found</h2>"); } }
public void SocketState_GetSocket() { // create a socket using to pass to a SocketState object Network.MakeSocket("localhost", out Socket sock, out IPAddress address); try { SocketState state = new SocketState(sock, -1); // the socket returned by GetSocket should be the same instance as // passed to the constructor Assert.AreEqual(sock, state.GetSocket()); } // make sure we close the socket when we are done testing our state finally { sock.Dispose(); } }
/// <summary> /// NetworkAction delegate which implements the server's part of the /// initial handshake. /// /// Creates a new Ship with the given name and a new unique ID and sets /// the SocketState's ID. /// /// Changes the state's callback method to one that handles command /// requests from the client then asks the clients for data. /// </summary> private void ReceivePlayerName(SocketState state) { // enumerate the complete received messages. IEnumerable <string> messages = GetTokens(state.GetStringBuilder()); // find the name in the complete messages string playerName = ""; if (messages.Any()) { playerName = messages.First(); state.GetStringBuilder().Clear(); } // if there wasn't a complete message continue the event loop else { Network.GetData(state); return; } // the id and world are being changed by callback methods (different threads) int playerID = 0; lock (world) { playerID = IDCounter++; // make a ship with a the name and give it a unique id // add ship to world world.MakeNewShip(playerName.TrimEnd(), playerID); // set the socket state ID state.SetID(playerID); } if (state.HasError) { HandleNetworkError(state); return; } // change the callback to handle incoming commands from the client state.SetNetworkAction(HandleClientCommands); // send the startup info to the client (ID and world size) string startupInfo = playerID + "\n" + world.GetSize() + "\n"; Network.Send(state.GetSocket(), startupInfo); // set FirstPlayerHasJoined to true if this is the first player and // get the start time if (!FirstPlayerHasJoined) { FirstPlayerHasJoined = true; // set the start time to now (current value will be server start time) startTime = DateTime.UtcNow; } // handshake is done print line that someone has connected Console.Out.WriteLine("A new Client has contacted the Server."); // add the client's socket to a set of all clients lock (clients) { clients.Add(state); } // ask the client for data (continue loop) Network.GetData(state); }