/// <summary> /// Decides which operation is requested depending on prefix of the data string. /// </summary> /// <param name="aData">Full incoming data string</param> /// <param name="aClient">Client that send the operation</param> private static void DecideOperation(string aData, TcpServerClient aClient) { string lOperationData = String.Empty; string lPrefix = GetDataPrefix(aData, out lOperationData); switch (lPrefix) { case PREFIX_NEWRM: CreateNewRoom(lOperationData, aClient); break; case PREFIX_SNDRM: SendAvailableRooms(aClient); break; case PREFIX_CONRM: ConnectToRoomAsSecondPlayer(lOperationData, aClient); break; case PREFIX_TDATA: FillPlayerTurnData(lOperationData, aClient); break; default: MessageBox.Show("Unknown data prefix."); break; //throw new Exception("Unknown data prefix."); } }
/// <summary> /// Checks continuously if this client is sending new data. /// Runs on a separate thread. /// </summary> /// <param name="aClient">Client to check for new data.</param> private static async void CheckClientForNewData(TcpServerClient aClient) { NetworkStream lNetworkStream = aClient.PlayerClient.GetStream(); try { while (aClient.PlayerClient.Client.Connected) { int byteCount = await lNetworkStream.ReadAsync(_BufferSize, 0, _BufferSize.Length); string ReceivedData = _EncodingInstance.GetString(_BufferSize, 0, byteCount); if (ReceivedData != String.Empty) { DecideOperation(ReceivedData, aClient); //Confirmation Message ? //byte[] ResponseBytes = _EncodingInstance.GetBytes(MESSAGE_CONFIRMED); //await lNetworkStream.WriteAsync(ResponseBytes, 0, ResponseBytes.Length); } Thread.Sleep(1); } } catch (Exception e) { Console.WriteLine(">>> " + e.Message); } lNetworkStream.Close(); aClient.PlayerClient.Close(); _ListConnectedClients.Remove(aClient); }
/// <summary> /// Send player/client the current game state (was their move valid etc. and the board state) /// </summary> /// <param name="aRoom">Room</param> /// <param name="aClient">Client the gets this data</param> /// <param name="aGameStateString">Board state data</param> private static void SendPlayerGameState(Room aRoom, TcpServerClient aClient, string aGameStateString) { DataGameState lGameState = new DataGameState(); lGameState.GameState = aGameStateString; lGameState.PlayGround = aRoom.PlayGround; SendData(aClient, String.Format("{0}{1}", PREFIX_GMEST, DataProcessor.SerializeGameStateData(lGameState))); }
/// <summary> /// Creates a new Play-Room. /// </summary> /// <param name="name">Name of the Room</param> /// <param name="player1">Player 1</param> public Room(string name, TcpServerClient player1) { this.Player1 = player1; this.Name = name; long ticks = DateTime.Now.Ticks; this.Id = String.Format("{0}-{1}", ticks, Guid.NewGuid().ToString()); this.Status = RoomState.WAITING_FOR_SECOND_PLAYER; }
/// <summary> /// Finds the room where this client is in. Assuming each client is only in one room!!! /// </summary> /// <param name="aClient">Client to search for</param> /// <returns>Room in which the client is</returns> private static Room GetRoomFromClient(TcpServerClient aClient) { foreach (Room lRoom in _ListRooms) { if (lRoom.Player1.ClientID == aClient.ClientID || lRoom.Player2.ClientID == aClient.ClientID) { return(lRoom); } } return(null); }
/// <summary> /// Continuously checks if a new client wants to connect to the server. /// Runs on a separate thread. /// </summary> private static async void CheckForNewConnections() { TcpClient Client; TcpServerClient ServerClient; while (_TcpGameServer != null && CurrentServerStatus == ServerStatus.Online) { try { //Client connect with server Client = await _TcpGameServer.AcceptTcpClientAsync(); ServerClient = new TcpServerClient(); ServerClient.PlayerClient = Client; //Public Key für RSA verschicken SendData(ServerClient, Cryptography.GetStringFromKey(Cryptography.PublicKey)); //Client verschlüsselt dann damit den symmetrischen Schlüssel und sendet Chiffre zurück //Chiffre mit Private Key hier entschlüsseln string lChiffre = WaitForResponse(ServerClient); Cryptography.SymmetricKey = Cryptography.RsaDecrypt(lChiffre, Cryptography.PrivateKey); //Sende BEREIT Nachricht an Client SendData(ServerClient, MESSAGE_CONFIRMED); //Client sendet Chiffre (AES) des Spielernamen (verschlüsselt durch symm. Schlüssel) string lChiffre_ClientName = WaitForResponse(ServerClient); //Chiffre wird hier mit symm. Schlüssel entschlüsselt string lClientName = Cryptography.AesDecrypt(lChiffre_ClientName, Cryptography.SymmetricKey); //Neuen Client anlegen (wird dann weiter unten gemacht) //Client should immediately send message with client name / player name, gets saved as TcpServerClient if (lClientName != String.Empty) { ServerClient.PlayerName = lClientName; } else { ServerClient.PlayerName = "Unknown Player"; } //Add ServerClient to the list of clients TryAddNewTcpClient(ServerClient); Thread.Sleep(1); } catch { } } }
/// <summary> /// Creates a new room, which then waits until a second player has joined. /// </summary> /// <param name="aData">Data required to creating a new room</param> /// <param name="aClient">Client that creates the room</param> private static void CreateNewRoom(string aData, TcpServerClient aClient) { DataRoom NewRoomData = DataProcessor.DeserializeRoomData(aData); Room GameRoom = new Room(NewRoomData.Name, aClient); _ListRooms.Add(GameRoom); Thread ThreadWaitForSecPlayer = new Thread(() => WaitForSecondPlayer(GameRoom)); ThreadWaitForSecPlayer.Start(); }
private static string WaitForResponse(TcpServerClient aClient) { NetworkStream lNetworkStream = aClient.PlayerClient.GetStream(); string JSON_string = String.Empty; while (JSON_string == String.Empty) { int byteCount = lNetworkStream.Read(_BufferSize, 0, _BufferSize.Length); JSON_string = _EncodingInstance.GetString(_BufferSize, 0, byteCount); Thread.Sleep(2); } return(JSON_string); }
/// <summary> /// Adds the second Player. /// </summary> /// <param name="player2">Player 2</param> /// <returns>Returns true if execution was successful.</returns> public bool AddSecondPlayer(TcpServerClient player2) { if (this.Status.Equals(RoomState.WAITING_FOR_SECOND_PLAYER) && this.Player2 == null) { this.Player2 = player2; this.Status = RoomState.PLAYING; this.ActivePlayer = this.Player1; this.PlayGround = new int[NUMBER_OF_ROWS, NUMBER_OF_COLUMNS]; return(true); } else { return(false); } }
/// <summary> /// Changes Player /// </summary> private void ChangePlayer() { if (this.ActivePlayer == this.Player1) { this.ActivePlayer = this.Player2; } else if (this.ActivePlayer == this.Player2) { this.ActivePlayer = this.Player1; } else { this.ActivePlayer = this.Player1; Console.WriteLine("ERROR: Active Player is neither Player1 nor Player2!"); } }
/// <summary> /// Connects a client to a room as the second player. /// </summary> /// <param name="aOperationData">Json string for room ID</param> /// <param name="aClient">Client to connect as second player</param> private static void ConnectToRoomAsSecondPlayer(string aOperationData, TcpServerClient aClient) { RoomID ID = new RoomID(); //DataProcessor.DeserializeRoomID(aOperationData); ID.ID = aOperationData; GetRoomFromID(ID).AddSecondPlayer(aClient); Thread.Sleep(5); if (GetRoomFromID(ID).Status == Room.RoomState.PLAYING) { SendData(aClient, MESSAGE_CONFIRMED); } else { SendData(aClient, MESSAGE_ERROR); } }
/// <summary> /// Executes a Turn from one Player. /// </summary> /// <param name="player">The executing Player</param> /// <param name="column">The selected column</param> /// <returns>Returns the state of the turn.</returns> public TurnState NextTurn(TcpServerClient player, int column) { if (this.Status != RoomState.PLAYING) { Console.WriteLine("ERROR: Room is not fully initialized!"); return(TurnState.NOT_VALID); } if (player == this.ActivePlayer) { int playerNumber = this.GetCurrentPlayerNumber(); if (playerNumber == 0) { return(TurnState.UNDEFINIED_PLAYER); } TurnState turnState = this.DropPiece(playerNumber, column); WinState winner = this.IsWinner(); if (winner == WinState.WINNER) { this.Status = RoomState.FINISHED; turnState = TurnState.WINNER; //return TurnState.WINNER; } else if (winner == WinState.DRAW) { this.Status = RoomState.FINISHED; turnState = TurnState.DRAW; } if (turnState != TurnState.NOT_VALID) { this.ChangePlayer(); } return(turnState); } else { return(TurnState.NOT_ACITVE_PLAYER); } }
/// <summary> /// Trys to add ServerClient to list of clients. Only works successfully when client list does not contain client yet. /// </summary> /// <param name="aClient">Client to add to list.</param> /// <returns>AddingSuccessful</returns> private static bool TryAddNewTcpClient(TcpServerClient aClient) { bool canAdd = true; foreach (TcpServerClient Client in _ListConnectedClients) { if (aClient.PlayerClient.Client.RemoteEndPoint == Client.PlayerClient.Client.RemoteEndPoint) { canAdd = false; } } if (canAdd) { _ListConnectedClients.Add(aClient); Thread lDataCheckThread = new Thread(() => CheckClientForNewData(aClient)); lDataCheckThread.Start(); return(true); } return(false); }
/// <summary> /// Send a client data. /// </summary> /// <param name="aClient">Client that gets the data</param> /// <param name="aData">Data to send</param> private static /*async*/ void SendData(TcpServerClient aClient, String aData) { try { if (aClient != null) { byte[] dataToSend = new byte[4096]; dataToSend = _EncodingInstance.GetBytes(aData); aClient.PlayerClient.GetStream().BeginWrite(dataToSend, 0, dataToSend.Length, null, null); //var byteCount = await aClient.PlayerClient.GetStream().ReadAsync(_BufferSize, 0, _BufferSize.Length); //var response = _EncodingInstance.GetString(_BufferSize, 0, byteCount); } } catch (SocketException e) { MessageBox.Show("Keine Verbindung möglich", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); } catch (Exception e) { MessageBox.Show(e.Message); } }
/// <summary> /// When clients the request a list of available rooms , they get the names and IDs (etc.) of those as a list. /// Sends client a json string with this list. /// </summary> /// <param name="aClient">Client that requested rooms</param> private static void SendAvailableRooms(TcpServerClient aClient) { bool DEBUG = false; //Start DEBUG if (DEBUG) { DataRoom room = new DataRoom(); room.Name = "TEST_ROOM"; TcpServerClient client = new TcpServerClient(); client.ClientID = "TEST_ID"; client.PlayerClient = new TcpClient(); client.PlayerName = "TEST_CLIENT"; CreateNewRoom(JsonConvert.SerializeObject(room), client); } //End DEBUG DataSendRooms RoomData = new DataSendRooms(_ListRooms); SendData(aClient, String.Format("{0}", DataProcessor.SerializeSendRoomsData(RoomData))); }
/// <summary> /// Fills the TurnData field in a room with the data received from a client. /// Also adds clients ID to the field for later search. /// </summary> /// <param name="aOperationData">Json string data for game state</param> /// <param name="aClient">Player client</param> private static void FillPlayerTurnData(string aOperationData, TcpServerClient aClient) { GetRoomFromClient(aClient).TurnData = DataProcessor.DeserializePlayerTurnData(aOperationData, aClient.ClientID); }
/// <summary> /// Send the player a signal that it's their turn. /// </summary> /// <param name="aClient">Client that gets the signal</param> private static void SendPlayerYourTurn(TcpServerClient aClient) { SendData(aClient, PREFIX_YOURT); }