/// <summary> /// Envia a mensagem para o servidor /// </summary> /// <param name="message"></param> /// <param name="type"></param> public void Send(byte[] message, ProtocolSICmdType type = ProtocolSICmdType.DATA) { try { // Envia os dados para o servidor byte[] packet = protocolSI.Make(type, message); networkStream.Write(packet, 0, packet.Length); } catch (Exception) { return; } }
/// <summary> /// Envia a mensagem para o cliente /// </summary> /// <param name="type"></param> /// <param name="mensagem"></param> private void Send(byte[] mensagem, ProtocolSICmdType type) { try { // Envia a mensagem byte[] packet = protocolSI.Make(type, mensagem); networkStream.Write(packet, 0, packet.Length); // Envia o ACK para o cliente byte[] ack = protocolSI.Make(ProtocolSICmdType.ACK); networkStream.Write(ack, 0, ack.Length); } catch (Exception ex) { Console.WriteLine("Erro: " + ex); return; } }
public byte[] Make( ProtocolSICmdType protocolSICmdType, byte[] data, int numOfBytesToPackFromData) { if (data.Length > 1400) { throw new Exception("O tamanho dos dados é maior que MAX_DATA_LENGTH (" + 1400.ToString() + ")"); } if (numOfBytesToPackFromData > data.Length) { throw new Exception("O número de bytes a copiar é maior que o tamanho dos dados"); } byte[] numArray = new byte[3 + numOfBytesToPackFromData]; numArray[0] = (byte)protocolSICmdType; numArray[1] = (byte)(numOfBytesToPackFromData / 256); numArray[2] = (byte)(numOfBytesToPackFromData % 256); Array.Copy((Array)data, 0, (Array)numArray, 3, numOfBytesToPackFromData); return(numArray); }
public static int EnviarDadosServidor(ProtocolSICmdType protocolSICmdType, byte[] msg) { int resposta = 0; // 0 ou 1 se estiver ok try { // cifrar msg byte[] msg_cifrada = cifrarComChaveSimetrica(msg); // CRIA A MENSAGEM DO TIPO DEFINIDO UTILIZANDO O PROTOCOLO SI byte[] packet = protocolSI.Make(protocolSICmdType, msg_cifrada); //escreve na stream networkStream.Write(packet, 0, packet.Length); // saber se recebeu dados (ACK) if (LerRespostaServidor()) { byte[] hashing = CriarHash_Assinar_Cifrar(msg); // CRIA A MENSAGEM DO TIPO NORMAL (para enviar a hash) UTILIZANDO O PROTOCOLO SI packet = protocolSI.Make(ProtocolSICmdType.NORMAL, hashing); //escreve na stream networkStream.Write(packet, 0, packet.Length); // saber se recebeu o hash (ACK) if (LerRespostaServidor()) { resposta = 1; } } } catch (SocketException) { MessageBox.Show("Não foi possivel conectar ao servidor"); return(resposta); } return(resposta); }
public void broadcast(string msg, ProtocolSICmdType cmd, string except = "") //Faz um broadcast para todos os jogadores { connection.WaitOne(); //Adquire controle do networkStream byte[] msgToSend; NetworkStream networkStream = tcpClient.GetStream(); foreach (ClientHandler client in room.getClientList()) { if (!client.nomeJogador.Equals(except)) { NetworkStream newNetworkStream = client.tcpClient.GetStream(); //Cria uma nova via de comunicação para o client byte[] ack = protocolSI.Make(ProtocolSICmdType.ACK); newNetworkStream.Write(ack, 0, ack.Length); msgToSend = protocolSI.Make(cmd, client.security.CifrarTexto(msg)); newNetworkStream.Write(msgToSend, 0, msgToSend.Length); esperaACK(); } } connection.ReleaseMutex(); //Libera o networkStream }
public int EnviarChaveServidor(ProtocolSICmdType protocolSICmdType, byte[] msg) { int ok = 0; try { // CRIA A MENSAGEM DO TIPO DATA UTILIZANDO O PROTOCOLO SI byte[] packet = protocolSI.Make(protocolSICmdType, msg); //escreve na stream networkStream.Write(packet, 0, packet.Length); if (LerRespostaServidor()) { ok = 1; // recebe ack } } catch (SocketException) { MessageBox.Show("Não foi possivel conectar ao servidor. funcao"); return(ok); } return(ok); }
public byte[] Make(ProtocolSICmdType protocolSICmdType) { return(this.Make(protocolSICmdType, 0)); }
public byte[] Make(ProtocolSICmdType protocolSICmdType, string data) { return(this.Make(protocolSICmdType, ProtocolSI.ConvertStringToByteArray(data))); }
public byte[] Make(ProtocolSICmdType protocolSICmdType, double data) { return(this.Make(protocolSICmdType, ProtocolSI.ConvertDoubleToByteArray(data))); }
public byte[] Make(ProtocolSICmdType protocolSICmdType, int data) { return(this.Make(protocolSICmdType, ProtocolSI.ConvertIntToByteArray(data))); }
public byte[] Make(ProtocolSICmdType protocolSICmdType, byte[] data) { return(this.Make(protocolSICmdType, data, data.Length)); }
private void trocaDePosicao(bool vencedor = false) { if (vencedor) { broadcast("", ProtocolSICmdType.USER_OPTION_7); esperaACK(); room.trocaJogadores(); } else if (room.getClientList().Count == 1) { room.trocaJogadores(); string msg = String.Format("1/Agora você é o jogador {0}", room.getPosJogador(nomeJogador)); byte[] msgByte = protocolSI.Make(ProtocolSICmdType.USER_OPTION_7, security.CifrarTexto(msg)); networkStream.Write(msgByte, 0, msgByte.Length); esperaACK(); } else { string outroJogador = room.getNomeJogador(room.getPosJogador(nomeJogador) == 1 ? 2 : 1); foreach (ClientHandler client in this.room.getClientList()) { if (client.nomeJogador.Equals(outroJogador)) { string msg = String.Format("0/O jogador {0} solicitou trocar de posição, você aceita?", nomeJogador); byte[] msgByte = protocolSI.Make(ProtocolSICmdType.USER_OPTION_7, security.CifrarTexto(msg)); connection.WaitOne(); //Adquire controle único do networkStream para fazer o broadcast NetworkStream newNetworkStream = client.tcpClient.GetStream(); //Cria uma nova via de comunicação para aquele client byte[] ack = protocolSI.Make(ProtocolSICmdType.ACK); newNetworkStream.Write(ack, 0, ack.Length); Thread.Sleep(100); newNetworkStream.Write(msgByte, 0, msgByte.Length); newNetworkStream.Read(protocolSI.Buffer, 0, protocolSI.Buffer.Length); ProtocolSICmdType protocolSICmdType = protocolSI.GetCmdType(); while (protocolSICmdType != ProtocolSICmdType.USER_OPTION_1 && protocolSICmdType != ProtocolSICmdType.USER_OPTION_2) { newNetworkStream.Read(protocolSI.Buffer, 0, protocolSI.Buffer.Length); protocolSICmdType = protocolSI.GetCmdType(); } connection.ReleaseMutex(); //Libera o networkStream if (protocolSICmdType == ProtocolSICmdType.USER_OPTION_1) { msg = "1/Solicitação aceita"; msgByte = protocolSI.Make(ProtocolSICmdType.USER_OPTION_7, security.CifrarTexto(msg)); networkStream.Write(msgByte, 0, msgByte.Length); broadcast("", ProtocolSICmdType.USER_OPTION_7, nomeJogador); esperaACK(); room.trocaJogadores(); return; } else { msg = "2/Solicitação negada"; msgByte = protocolSI.Make(ProtocolSICmdType.USER_OPTION_7, security.CifrarTexto(msg)); networkStream.Write(msgByte, 0, msgByte.Length); esperaACK(); return; } } } } }
private void threadHandler() //Trata as mensagens que chegam e que são enviadas { networkStream = this.tcpClient.GetStream(); protocolSI = new ProtocolSI(); Boolean trocaPosicao = false; while (protocolSI.GetCmdType() != ProtocolSICmdType.EOT) //Enquanto a thread não receber ordens para terminar { networkStream.Read(protocolSI.Buffer, 0, protocolSI.Buffer.Length); ProtocolSICmdType cmd = protocolSI.GetCmdType(); string msg; byte[] msgByte; switch (protocolSI.GetCmdType()) { case ProtocolSICmdType.PUBLIC_KEY: security.setPublicKey(protocolSI.GetStringFromData()); Console.WriteLine("Recebi uma chave pública"); enviaACK(); simetricKey = protocolSI.Make(ProtocolSICmdType.SYM_CIPHER_DATA, security.getSimetricKey()); networkStream.Write(simetricKey, 0, simetricKey.Length); esperaACK(); IV = protocolSI.Make(ProtocolSICmdType.IV, security.getIV()); networkStream.Write(IV, 0, IV.Length); esperaACK(); break; case ProtocolSICmdType.USER_OPTION_1: //Adquire o nome do jogador connection.WaitOne(); //Caso no qual é feito um broadcast e a thread "errada" recebe o ACK e, portanto connection.ReleaseMutex(); //espera até que a thread "correta" receba o ACK para poder voltar a esperar nova mensagem nomeJogador = security.DecifrarTexto(protocolSI.GetStringFromData()); Console.WriteLine("Jogador {0} - {1}, conectou-se", clientID, nomeJogador); enviaACK(); break; case ProtocolSICmdType.USER_OPTION_2: //Atualiza os jogadores presentes na sala string salaDesejada = security.DecifrarTexto(protocolSI.GetStringFromData()); byte[] newJogador; foreach (room sala in rooms) //Percorre a lista de salas verificando se a sala na qual o cliente deseja conectar-se já existe { if (sala.getName() == salaDesejada) { if (!sala.isFull()) //Verifica se a sala não está cheia { sala.addClientToRoom(this); this.room = sala; break; } else { goto SalaCheia; } } } if (room == null) //Cria a sala caso a mesma não exista { room = new room(salaDesejada); rooms.Add(room); room.addClientToRoom(this); msg = System.DateTime.Now.ToString(); room.writeLog(msg); } Console.WriteLine("{0} entrou na sala {1}", nomeJogador, salaDesejada); enviaACK(); if (room.getClientList().Count == 1) //Se aquele jogador é o único na sala { //Coloca o jogador como o jogador 1 room.setJogador(nomeJogador); msg = String.Format("1/{0}/", nomeJogador); newJogador = protocolSI.Make(ProtocolSICmdType.USER_OPTION_1, security.CifrarTexto(msg)); networkStream.Write(newJogador, 0, newJogador.Length); esperaACK(); } else if (room.getClientList().Count == 2) //Se é o 2º jogador a entrar na sala { int posNovoJogador; room.setJogador(nomeJogador); foreach (ClientHandler client in room.getClientList()) { if (client.clientID != clientID) { posNovoJogador = room.getNomeJogador(2) == nomeJogador ? 2 : 1; //Descobre qual será a posição do novo jogador msg = String.Format("{0}/{1}/{2}", posNovoJogador, nomeJogador, jogadores); newJogador = protocolSI.Make(ProtocolSICmdType.USER_OPTION_1, client.security.CifrarTexto(msg)); broadcast(msg, ProtocolSICmdType.USER_OPTION_1, nomeJogador); //Coloca-se na posição que resta networkStream.Write(newJogador, 0, newJogador.Length); esperaACK(); } else //Envia o nome do jogador que já está na sala para o novo jogador { int posJogadorPresente = room.getNomeJogador(1) != nomeJogador ? 1 : 2; msg = String.Format("{0}/{1}/{2}", posJogadorPresente, room.getNomeJogador(posJogadorPresente), true == room.isMultiplePlayers() ? "true" : "false"); msgByte = protocolSI.Make(ProtocolSICmdType.USER_OPTION_1, security.CifrarTexto(msg)); networkStream.Write(msgByte, 0, msgByte.Length); esperaACK(); } } //Broadcast que informa que há 2 jogadores na sala e, portanto o jogo pode iniciar broadcast(" ", ProtocolSICmdType.USER_OPTION_3); } else //Se a sala já tem 2 jogadores { //Coloca os próximos jogadores na fila room.setJogador(nomeJogador); msg = String.Format("3/{0}/{1}/{2}/{3}/{4}/{5}/{6}", room.getNomeJogador(1), room.getNomeJogador(2), room.getPontos(room.getNomeJogador(1)), room.getPontos(room.getNomeJogador(2)), room.getPontos("empates"), jogadores, room.getProximoJogadores()); newJogador = protocolSI.Make(ProtocolSICmdType.USER_OPTION_1, security.CifrarTexto(msg)); networkStream.Write(newJogador, 0, newJogador.Length); msg = String.Format("4/{0}/{1}", jogadores, room.getProximoJogadores()); broadcast(msg, ProtocolSICmdType.USER_OPTION_1); esperaACK(); } break; SalaCheia: msgByte = protocolSI.Make(ProtocolSICmdType.USER_OPTION_3); networkStream.Write(msgByte, 0, msgByte.Length); esperaACK(); break; case ProtocolSICmdType.DATA: //Transmite o que o jogador disse para o chat msg = $"{System.DateTime.Now.ToString("HH:mm:ss")} - {nomeJogador} : {security.DecifrarTexto(protocolSI.GetStringFromData())}"; Console.WriteLine(msg); broadcast(msg, ProtocolSICmdType.DATA); //Broadcast da mensagem para todos os jogadores room.writeLog(msg); //Escreve para o arquivo de texto as mensagens do chat break; case ProtocolSICmdType.USER_OPTION_3: //Trata da jogada executada utilizando assinaturas digitais //Recebe o movimento cifrado string move = security.DecifrarTexto(protocolSI.GetStringFromData()); //Espera pelo hash assinado do movimento cifrado com a chave privada networkStream.Read(protocolSI.Buffer, 0, protocolSI.Buffer.Length); while (protocolSI.GetCmdType() != ProtocolSICmdType.USER_OPTION_4) { networkStream.Read(protocolSI.Buffer, 0, protocolSI.Buffer.Length); } string moveSign = security.DecifrarTexto(protocolSI.GetStringFromData()); //Verifica a autenticidade do movimento if (security.verifySignData(move, moveSign)) { string[] coordenadas = move.Split('/'); int line = int.Parse(coordenadas[0]); int col = int.Parse(coordenadas[1]); string symbolPlayer = room.getNomeJogador(1) == this.nomeJogador ? "X" : "O"; switch (room.move(line, col, this.nomeJogador)) { case -1: //Movimento é inválido msg = "Movimento inválido, tente novamente!"; byte[] invalid = protocolSI.Make(ProtocolSICmdType.USER_OPTION_4, security.CifrarTexto(msg)); networkStream.Write(invalid, 0, invalid.Length); break; case 0: //Movimento válido broadcast(String.Format("{0}{1}/{2}", line, col, symbolPlayer), ProtocolSICmdType.USER_OPTION_5); break; case 1: //Jogo termina com um ganhador broadcast(String.Format("{0}{1}/{2}", line, col, symbolPlayer), ProtocolSICmdType.USER_OPTION_5); Thread.Sleep(100); broadcast(String.Format("{0}/ganhou!", nomeJogador), ProtocolSICmdType.USER_OPTION_6); Thread.Sleep(100); if (trocaPosicao) { trocaDePosicao(room.isMultiplePlayers() == true ? true : false); trocaPosicao = false; } break; case 2: //Jogo termina em empate broadcast(String.Format("{0}{1}/{2}", line, col, symbolPlayer), ProtocolSICmdType.USER_OPTION_5); Thread.Sleep(100); broadcast(String.Format("/Empate!", nomeJogador), ProtocolSICmdType.USER_OPTION_6); Thread.Sleep(100); if (trocaPosicao) { trocaDePosicao(room.isMultiplePlayers() == true ? true : false); trocaPosicao = false; } break; case 3: //Jogador incorreto tentou fazer o movimento msg = "Espere a sua vez!"; byte[] jogadorIncorreto = protocolSI.Make(ProtocolSICmdType.USER_OPTION_4, security.CifrarTexto(msg)); networkStream.Write(jogadorIncorreto, 0, jogadorIncorreto.Length); break; default: Console.WriteLine("Algo de errado aconteceu ao executar room.move"); break; } } else { Console.WriteLine("Mensagem enviada inválida"); msg = "Ocorreu algum erro, tente novamente!"; byte[] invalid = protocolSI.Make(ProtocolSICmdType.USER_OPTION_7, security.CifrarTexto(msg)); networkStream.Write(invalid, 0, invalid.Length); } break; case ProtocolSICmdType.USER_OPTION_5: //Jogador solicitou troca de posição trocaPosicao = true; if (!room.jogo.jogoComecou()) { trocaDePosicao(); } break; case ProtocolSICmdType.USER_OPTION_6: //Jogador solicitou permitir vários jogadores room.multiplePlayers(); msg = "Múltiplos jogadores habilitado"; broadcast(msg, ProtocolSICmdType.USER_OPTION_8); break; case ProtocolSICmdType.SECRET_KEY: //Recebe a senha do usuário Console.WriteLine("Recebi a senha"); string senha = security.DecifrarTexto(protocolSI.GetStringFromData()); if (security.VerifyLogin(this.nomeJogador, senha)) { //Autentica o jogador Console.WriteLine("{0} autenticado com sucesso", this.nomeJogador); msg = String.Format("{0}/{1}", nomeJogador, security.GetPoints(nomeJogador)); byte[] ack = protocolSI.Make(ProtocolSICmdType.ACK, security.CifrarTexto(msg)); networkStream.Write(ack, 0, ack.Length); jogadores = jogadores + nomeJogador + ',' + security.GetPoints(nomeJogador) + ';'; } else { Console.WriteLine("{0} senha incorreta", this.nomeJogador); byte[] msgConnection = protocolSI.Make(ProtocolSICmdType.USER_OPTION_3); networkStream.Write(msgConnection, 0, msgConnection.Length); esperaACK(); } break; case ProtocolSICmdType.EOT: //Finaliza a sessão do jogador Console.WriteLine("Ending Thread from {0}", nomeJogador); if (room != null) { security.setPoints(nomeJogador, room.getPontos(nomeJogador) + security.GetPoints(nomeJogador)); if (room.getClientList().Count >= 2) { msg = String.Format("Jogador {0} deixou a sala/{1}", nomeJogador, nomeJogador); broadcast(msg, ProtocolSICmdType.USER_OPTION_9, nomeJogador); } } room.novoJogo(); break; case ProtocolSICmdType.ACK: //Caso no qual é feito um broadcast e a thread "errada" recebe o ACK e, portanto connection.WaitOne(); //espera até que a thread "correta" receba o ACK para poder voltar a esperar nova mensagem connection.ReleaseMutex(); break; default: break; } } networkStream.Close(); this.tcpClient.Close(); if (room != null) { this.room.removeClientOfRoom(this); this.room = null; } }
static void Main(string[] args) { Console.WriteLine(" == CLIENT == "); Console.Title = "CLIENT"; TcpClient client = null; NetworkStream stream = null; ProtocolSI protocol = null; byte[] packet = null; string temp = ""; int bytesRead; try { protocol = new ProtocolSI(); client = new TcpClient(); client.Connect(IPAddress.Loopback, PORT); stream = client.GetStream(); ProtocolSICmdType cmd = ProtocolSICmdType.NORMAL; do { Console.WriteLine("\n\nOpções:"); Console.WriteLine("\t1) Send INT"); Console.WriteLine("\t2) Send STRING"); Console.WriteLine("\t9) END"); Console.Write("\t\tOpção: "); switch (Console.ReadKey().Key) { case ConsoleKey.D1: // enviar int packet = protocol.Make(ProtocolSICmdType.NORMAL, 1234); temp = "int"; break; case ConsoleKey.D2: // enviar string packet = protocol.Make(ProtocolSICmdType.DATA, "Estou na aula de SI"); temp = "string"; break; case ConsoleKey.D9: // EOT cmd = ProtocolSICmdType.EOT; packet = protocol.Make(ProtocolSICmdType.EOT); temp = "eot"; break; default: Console.WriteLine("\nInvalid option."); break; } stream.Write(packet, 0, packet.Length); Console.WriteLine($"Enviado: {temp}"); // receber confirmação stream.Read(protocol.Buffer, 0, protocol.Buffer.Length); if (protocol.GetCmdType() == ProtocolSICmdType.ACK) { Console.WriteLine("Confirmação recebida (ACK)."); } else { Console.WriteLine("Confirmação incorreta"); } } while (cmd != ProtocolSICmdType.EOT); Console.WriteLine("Comunicação Terminada. <tecla para terminar>"); } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } finally { if (client != null) { client.Dispose(); } if (stream != null) { stream.Dispose(); } } Console.ReadKey(); }