// O construtor da classe recebe uma conexão TCP e um pacote. public Conexao(TcpClient tcpCon, Pacote pacoteRecebido) { this.tcpCliente = tcpCon; this.pacoteRecebido = pacoteRecebido; // Instancia a thread que irá receber o cliente e aguarda por mensagens thrSender = new Thread(AceitaCliente); // A própria thread chama o método AceitaCliente() thrSender.Start(); }
// Ocorre quando o novo cliente é aceito private void AceitaCliente() { this.srRecebe = new StreamReader(tcpCliente.GetStream()); this.swEnvia = new StreamWriter(tcpCliente.GetStream()); // Se o pacote ja existe e o comando dele é de Conectar então não preciso fazer nada, do contrário devo ler a informação que vier if (this.pacoteRecebido != null && this.pacoteRecebido.Comando == Comando.Conectar) { } else { // Lê as informações de conta que vieram do cliente string conteudoRecebido = this.srRecebe.ReadLine(); // Limpo o pacote atual, caso dê alguma treta não vai seguir adiante com o pacote velho this.pacoteRecebido = null; if (conteudoRecebido != null) { this.pacoteRecebido = JsonConvert.DeserializeObject<Pacote>(conteudoRecebido); } } // Se tem pacote vou trabalhar com ele if (this.pacoteRecebido != null) { this.UsuarioConexao = pacoteRecebido.Usuario; Pacote pacoteEnviar = new Pacote(); pacoteEnviar.Usuario = "Administrator"; // Se é um pacote para parar a escuta, então paro! if (pacoteRecebido.Comando == Comando.PararEscuta) { FechaConexao(); return; } else if (this.UsuarioConexao != "" && pacoteRecebido.Comando == Comando.Conectar) // Se esta conexão não tem usuário e o comando é pedindo para conectar... { // Verifica se o nome do usuário ja não existe na lista de usuários if (ChatServer.htUsuarios.Contains(this.UsuarioConexao) == true) { // Comando é que este nome ja está sendo utilizado pacoteEnviar.Comando = Comando.NomeReservado; pacoteEnviar.Mensagem = "Este nome ja está sendo utilizado."; string objEnviar = JsonConvert.SerializeObject(pacoteEnviar); this.swEnvia.WriteLine(objEnviar); this.swEnvia.Flush(); FechaConexao(); return; } // Se o nome do usuário malandro é igual ao nome do administrador else if (this.UsuarioConexao == "Administrator") { // Comando é que este nome de usuário não pode ser utilizado pacoteEnviar.Comando = Comando.NomeReservado; pacoteEnviar.Mensagem = "Este nome é reservado."; string objEnviar = JsonConvert.SerializeObject(pacoteEnviar); this.swEnvia.WriteLine(objEnviar); this.swEnvia.Flush(); FechaConexao(); return; } else { // Comando é que foi conectado com sucesso pacoteEnviar.Comando = Comando.ConectadoComSucesso; pacoteEnviar.Mensagem = ""; string objEnviar = JsonConvert.SerializeObject(pacoteEnviar); this.swEnvia.WriteLine(objEnviar); this.swEnvia.Flush(); // Adiciona o usuário na lista e começa a escutar as mensagem vindas dele ChatServer.AdicionaUsuario(tcpCliente, this.UsuarioConexao); } } else { FechaConexao(); return; } try { // Continua aguardando por uma mensagem enviada pelo usuário while ((strResposta = this.srRecebe.ReadLine()) != "") { // Se o conteúdo enviado e null então removo o usupário da lista if (strResposta == null) { ChatServer.RemoveUsuario(tcpCliente); } else { // Agora vou tratar as próximas requisições pacoteRecebido = JsonConvert.DeserializeObject<Pacote>(strResposta); switch (pacoteRecebido.Comando) { case Comando.NomeReservado: // Ele está de brincadeira com este comando, vou remover este engraçadinho ChatServer.RemoveUsuario(tcpCliente); break; case Comando.ConectadoComSucesso: // Ele está de brincadeira com este comando, vou remover este engraçadinho ChatServer.RemoveUsuario(tcpCliente); break; case Comando.ListaDeUsuarios: // Ele está de brincadeira com este comando, vou remover este engraçadinho ChatServer.RemoveUsuario(tcpCliente); break; case Comando.Mensagem: // Envia mensagem normal para todos os outros usuários ChatServer.EnviaMensagem(pacoteRecebido); break; case Comando.MensagemPrivada: // Envia a mensagem apenas para o usuário determinado ChatServer.EnviaMensagemPrivada(pacoteRecebido); break; case Comando.EnviarArquivo: // Envia a mensagem dizendo que um usuário deseja enviar um arquivo para o outro ChatServer.EnviarArquivo(pacoteRecebido); break; case Comando.AceiteDoArquivo: ChatServer.AceiteDoArquivo(pacoteRecebido); break; case Comando.EnviandoArquivo: ChatServer.EnviandoArquivo(pacoteRecebido); break; case Comando.ArquivoRecusado: ChatServer.ArquivoRecusado(pacoteRecebido); break; case Comando.Conectar: // Ele está de brincadeira com este comando, vou remover este engraçadinho ChatServer.RemoveUsuario(tcpCliente); break; default: // Ele está de brincadeira, vou remover este engraçadinho ChatServer.RemoveUsuario(tcpCliente); break; } } } } catch { // Se algo está errado com este usuário, disconecto o mesmo. ChatServer.RemoveUsuario(tcpCliente); } } }
public void ParaAEscuta() { this.ServidorRodando = false; TcpClient tcpc = new TcpClient(); tcpc.Connect(this.EnderecoIP, this.porta); StreamWriter swSenderSender = new StreamWriter(tcpc.GetStream()); Pacote pacoteEnviar = new Pacote(); pacoteEnviar.Comando = Comando.PararEscuta; pacoteEnviar.Usuario = ChatServer.NomeAdministrador; pacoteEnviar.Mensagem = ChatServer.IDAdministrador; string objEnviar = JsonConvert.SerializeObject(pacoteEnviar); swSenderSender.WriteLine(objEnviar); swSenderSender.Flush(); swSenderSender = null; tcpc.Close(); //ChatServer.tlsClient.Stop(); //this.thrListener.Abort(); }
// Envia mensagens administrativas public static void EnviaMensagemDeAdministrador(string mensagem) { // Primeiro de tudo, exibe na aplicação quem diz o que e = new StatusChangedEventArgs(ChatServer.NomeAdministrador + ": " + mensagem); OnStatusChanged(e); // Cria um array de clientes TCP, o tamanho é o número de usuários que nós temos nas tabelas hash TcpClient[] tcpClientes = new TcpClient[ChatServer.htUsuarios.Count]; // Copia os objetos TcpClient para um array ChatServer.htUsuarios.Values.CopyTo(tcpClientes, 0); // Stream que irá enviar a mensagem para cada usuário StreamWriter swEnviador; // Laço sobre a lista de clientes TCP for (int i = 0; i < tcpClientes.Length; i++) { // Tentando enviar a mensagem para cada try { // Se a mensagem está vazia ou a conexão é null, cai fora if (mensagem.Trim() == "" || tcpClientes[i] == null) { continue; } // Envia a mensagem para o atual usuário do loop swEnviador = new StreamWriter(tcpClientes[i].GetStream()); // Criando o pacote para enviar Pacote pacoteEnviar = new Pacote(); pacoteEnviar.Comando = Comando.MensagemAdministrador; pacoteEnviar.Usuario = ChatServer.NomeAdministrador; pacoteEnviar.Mensagem = ChatServer.NomeAdministrador + ": " + mensagem; // Serializa o pacote string objEnviar = JsonConvert.SerializeObject(pacoteEnviar); swEnviador.WriteLine(objEnviar); swEnviador.Flush(); swEnviador = null; } catch // Se ocorreu algum problema o usuário não está mais conectado. Vou remover ele { RemoveUsuario(tcpClientes[i]); } } }
// Quando o Usuario envia uma mensagem dizendo que deseja enviar um arquivo para o UsuarioDestino public static void EnviarArquivo(Pacote pacote) { StreamWriter swEnviar; // Exibe na aplicação quem quer enviar o arquivo e para quem e = new StatusChangedEventArgs(pacote.Usuario + " quer enviar o arquivo " + pacote.NomeArquivo + " arquivo para " + pacote.UsuarioDestino); OnStatusChanged(e); TcpClient clienteTCPOrigem = null; TcpClient clienteTCPDestino = null; try { // Busca o cliente pela própria chave da hash table, não precisa de laço for e tal... if ((clienteTCPDestino = (TcpClient)ChatServer.htUsuarios[pacote.UsuarioDestino]) != null) { // Envia a mensagem para o usuário específico swEnviar = new StreamWriter(clienteTCPDestino.GetStream()); Pacote pacoteEnviar = new Pacote(); pacoteEnviar.Comando = Comando.EnviarArquivo; pacoteEnviar.Mensagem = pacote.Usuario + " deseja lhe enviar o arquivo " + pacote.NomeArquivo; pacoteEnviar.Usuario = pacote.Usuario; pacoteEnviar.UsuarioDestino = pacote.UsuarioDestino; pacoteEnviar.NomeArquivo = pacote.NomeArquivo; pacoteEnviar.TamanhoArquivo = pacote.TamanhoArquivo; pacoteEnviar.ConteudoArquivo = pacote.ConteudoArquivo; string objEnviar = JsonConvert.SerializeObject(pacoteEnviar); swEnviar.WriteLine(objEnviar); swEnviar.Flush(); swEnviar = null; } // Busca o cliente pela própria chave da hash table, não precisa de laço for e tal... if ((clienteTCPOrigem = (TcpClient)ChatServer.htUsuarios[pacote.Usuario]) != null) { // Envia a mensagem para o usuário específico swEnviar = new StreamWriter(clienteTCPOrigem.GetStream()); Pacote pacoteEnviar = new Pacote(); pacoteEnviar.Comando = Comando.MensagemPrivada; pacoteEnviar.Mensagem = "Você deseja enviar o arquivo " + pacote.NomeArquivo + " para " + pacote.UsuarioDestino; pacoteEnviar.Usuario = pacote.Usuario; pacoteEnviar.UsuarioDestino = pacote.UsuarioDestino; pacoteEnviar.NomeArquivo = pacote.NomeArquivo; pacoteEnviar.TamanhoArquivo = pacote.TamanhoArquivo; pacoteEnviar.ConteudoArquivo = pacote.ConteudoArquivo; string objEnviar = JsonConvert.SerializeObject(pacoteEnviar); swEnviar.WriteLine(objEnviar); swEnviar.Flush(); swEnviar = null; } } catch // Se tiver algum problema provavelmente o usuário não está mais conectado, vou remover ele da lista { RemoveUsuario(clienteTCPDestino); } }
// Envia a lista de usuário atualizada para todos os usuários conectados public static void EnviaListaDeUsuariosAtualizada() { Hashtable listaDeUsuariosAtualizadaEnviar = new Hashtable(); foreach (DictionaryEntry entry in ChatServer.htUsuarios) { // Cria lista valor/valor listaDeUsuariosAtualizadaEnviar.Add(entry.Key, entry.Key); } StreamWriter swSenderSender; // Create an array of TCP clients, the size of the number of users we have TcpClient[] tcpClients = new TcpClient[ChatServer.htUsuarios.Count]; // Copy the TcpClient objects into the array ChatServer.htUsuarios.Values.CopyTo(tcpClients, 0); // Loop through the list of TCP clients for (int i = 0; i < tcpClients.Length; i++) { // Try sending a message to each try { // If the message is blank or the connection is null, break out if (tcpClients[i] == null) { continue; } // Send the message to the current user in the loop swSenderSender = new StreamWriter(tcpClients[i].GetStream()); Pacote pacoteEnviar = new Pacote(); pacoteEnviar.Comando = Comando.ListaDeUsuarios; pacoteEnviar.Usuario = ChatServer.NomeAdministrador; pacoteEnviar.ListaDeUsuarios = listaDeUsuariosAtualizadaEnviar; string objEnviar = JsonConvert.SerializeObject(pacoteEnviar); swSenderSender.WriteLine(objEnviar); swSenderSender.Flush(); swSenderSender = null; } catch (Exception ex) // If there was a problem, the user is not there anymore, remove him { RemoveUsuario(tcpClients[i]); throw ex; } } }
// Envia mensagens de um usuário para todos os outros public static void EnviaMensagem(Pacote pacote) { StreamWriter swSenderSender; // First of all, show in our application who says what e = new StatusChangedEventArgs(pacote.Usuario + " disse: " + pacote.Mensagem); OnStatusChanged(e); // Create an array of TCP clients, the size of the number of users we have TcpClient[] tcpClients = new TcpClient[ChatServer.htUsuarios.Count]; // Copy the TcpClient objects into the array ChatServer.htUsuarios.Values.CopyTo(tcpClients, 0); // Loop through the list of TCP clients for (int i = 0; i < tcpClients.Length; i++) { // Try sending a message to each try { // If the message is blank or the connection is null, break out if (pacote.Mensagem.Trim() == "" || tcpClients[i] == null) { continue; } // Send the message to the current user in the loop swSenderSender = new StreamWriter(tcpClients[i].GetStream()); Pacote pacoteEnviar = new Pacote(); pacoteEnviar.Comando = Comando.Mensagem; pacoteEnviar.Mensagem = pacote.Usuario + " disse: " + pacote.Mensagem; string objEnviar = JsonConvert.SerializeObject(pacoteEnviar); swSenderSender.WriteLine(objEnviar); swSenderSender.Flush(); swSenderSender = null; } catch // If there was a problem, the user is not there anymore, remove him { RemoveUsuario(tcpClients[i]); } } }
// Este método é chamado de uma thread diferente e serve para atualizar o textbox de log do chat private void UpdateLog(Pacote pacote) { // Adiciona a linha e rola o texto para baixo txtLog.AppendText(pacote.Mensagem + "\r\n"); }
private void tsmi_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { // Guarda o path do arquivo PathArquivo = ofd.FileName; FileInfo fi = new FileInfo(ofd.FileName); // Enviando para o Servidor->UsuarioDestino a mensagem dizendo que eu quero enviar um arquivo pacoteEnviar = new Pacote(); pacoteEnviar.Comando = Comando.EnviarArquivo; pacoteEnviar.Usuario = this.Usuario; pacoteEnviar.UsuarioDestino = lbUsuarios.Text; pacoteEnviar.Mensagem = null; pacoteEnviar.NomeArquivo = Path.GetFileName(ofd.FileName); pacoteEnviar.TamanhoArquivo = fi.Length.ToString(); pacoteEnviar.ConteudoArquivo = null; string objEnviar = JsonConvert.SerializeObject(pacoteEnviar); swEnviar.WriteLine(objEnviar); swEnviar.Flush(); txtMensagem.Lines = null; } }
// Responsável por gerenciar as mensagens private void RecebeMensagens() { // Recebe os pacotes do servidor srReceber = new StreamReader(tcpServidor.GetStream()); // Lê o pacote recebido string retorno = srReceber.ReadLine(); pacoteRecebido = JsonConvert.DeserializeObject<Pacote>(retorno); // Conforme o comando recebido vejo o que aconteceu if (pacoteRecebido.Comando == Comando.ConectadoComSucesso) { // Atualiza o form para informar que se conectou this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { "Conectado com sucesso!" }); } else // Como o comando não foi de conectado, então qualquer outro comando neste momento é porque não se conectou { string motivo = "Não conectado: " + pacoteRecebido.Mensagem; // Atualiza o form com o motivo de porque não pode se conectar this.Invoke(new CloseConnectionCallback(this.FinalizaConexao), new object[] { motivo }); // Sai do método return; } // Enquanto estiver conectado lê as linhas que vierem do servidor while (Conectado) { try { string conteudoRecebido = srReceber.ReadLine(); if (conteudoRecebido != null) { pacoteRecebido = JsonConvert.DeserializeObject<Pacote>(conteudoRecebido); if (pacoteRecebido.Comando == Comando.ListaDeUsuarios) { this.Invoke(new UpdateListaUsuariosCallback(this.UpdateLista), new object[] { pacoteRecebido.ListaDeUsuarios }); } else if (pacoteRecebido.Comando == Comando.EnviarArquivo || pacoteRecebido.Comando == Comando.AceiteDoArquivo || pacoteRecebido.Comando == Comando.ArquivoRecusado || pacoteRecebido.Comando == Comando.EnviandoArquivo) { // Estão querendo me enviar um arquivo if (pacoteRecebido.Comando == Comando.EnviarArquivo && RecebendoArquivo == false) { if (MessageBox.Show(this.Usuario + " você deseja receber o arquivo: " + pacoteRecebido.NomeArquivo + " de " + pacoteRecebido.Usuario + "?", "Receber arquivo", MessageBoxButtons.YesNo) == DialogResult.Yes) { RecebendoArquivo = true; // Criando novo pacote pacoteEnviar = new Pacote(); pacoteEnviar.Comando = Comando.AceiteDoArquivo; pacoteEnviar.Usuario = this.Usuario; pacoteEnviar.Mensagem = pacoteRecebido.Mensagem; pacoteEnviar.NomeArquivo = pacoteRecebido.NomeArquivo; pacoteEnviar.TamanhoArquivo = pacoteRecebido.TamanhoArquivo; pacoteEnviar.ConteudoArquivo = null; pacoteEnviar.UsuarioDestino = pacoteRecebido.Usuario; string objEnviar = JsonConvert.SerializeObject(pacoteEnviar); swEnviar.WriteLine(objEnviar); swEnviar.Flush(); } } else if (pacoteRecebido.Comando == Comando.AceiteDoArquivo) // Aceitou o arquivo, vou enviar ele agora { // Lê o arquivo de forma binária FileStream fsr = new FileStream(PathArquivo, FileMode.Open); byte[] bufferRead = new byte[fsr.Length]; BinaryReader br = new BinaryReader(fsr); br.Read(bufferRead, 0, (int)fsr.Length); br.Close(); // Converte o arquivo em base64 para poder enviar como string string arquivoConvertido = Convert.ToBase64String(bufferRead); // Criando novo pacote pacoteEnviar = new Pacote(); pacoteEnviar.Comando = Comando.EnviandoArquivo; pacoteEnviar.Usuario = this.Usuario; pacoteEnviar.Mensagem = null; pacoteEnviar.UsuarioDestino = pacoteRecebido.Usuario; pacoteEnviar.NomeArquivo = Path.GetFileName(this.PathArquivo); pacoteEnviar.TamanhoArquivo = bufferRead.LongLength.ToString(); pacoteEnviar.ConteudoArquivo = arquivoConvertido; string objEnviar = JsonConvert.SerializeObject(pacoteEnviar); swEnviar.WriteLine(objEnviar); swEnviar.Flush(); } else if (pacoteRecebido.Comando == Comando.EnviandoArquivo && RecebendoArquivo) // O arquivo foi aceito e estou recebendo ele agora { SaveFileDialog sfd = new SaveFileDialog(); sfd.RestoreDirectory = true; sfd.FileName = pacoteRecebido.NomeArquivo; if (sfd.ShowDialog() == DialogResult.OK) { byte[] bufferFromBase4 = Convert.FromBase64String(pacoteRecebido.ConteudoArquivo); FileStream fsw2 = new FileStream(sfd.FileName, FileMode.Create); BinaryWriter bw2 = new BinaryWriter(fsw2); bw2.Write(bufferFromBase4); bw2.Close(); RecebendoArquivo = false; } } else { // Criando novo pacote pacoteEnviar = new Pacote(); pacoteEnviar.Comando = Comando.ArquivoRecusado; pacoteEnviar.Usuario = this.Usuario; pacoteEnviar.UsuarioDestino = pacoteRecebido.Usuario; pacoteEnviar.Mensagem = pacoteRecebido.Mensagem; pacoteEnviar.NomeArquivo = pacoteRecebido.NomeArquivo; pacoteEnviar.TamanhoArquivo = pacoteRecebido.TamanhoArquivo; pacoteEnviar.ConteudoArquivo = null; string objEnviar = JsonConvert.SerializeObject(pacoteEnviar); swEnviar.WriteLine(objEnviar); swEnviar.Flush(); } } else { this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { pacoteRecebido.Mensagem }); } } } catch (SocketException SocketEx) { Conectado = false; //throw SocketEx; } catch (Exception ex) { Conectado = false; //throw ex; } } }
// Inicia a conexão private void IniciaConexao() { endereçoIP = IPAddress.Parse(txtIp.Text); // Inicia a conexão com o servidor do chat tcpServidor = new TcpClient(); tcpServidor.Connect(endereçoIP, (int)nudPorta.Value); // Define que está conectado Conectado = true; Usuario = txtUsuario.Text; // Desabilita e habilita os devidos campos txtIp.Enabled = false; txtUsuario.Enabled = false; nudPorta.Enabled = false; txtMensagem.Enabled = true; btnEnviar.Enabled = true; btnConectar.Text = "Desconectar"; // Stream para envio de pacotes para o servidor swEnviar = new StreamWriter(tcpServidor.GetStream()); // Criando novo pacote pacoteEnviar = new Pacote(); pacoteEnviar.Comando = Comando.Conectar; pacoteEnviar.Usuario = this.Usuario; pacoteEnviar.Mensagem = "entrando no chat..."; string objEnviar = JsonConvert.SerializeObject(pacoteEnviar); swEnviar.WriteLine(objEnviar); swEnviar.Flush(); // Inicia a thread para receber pacotes do servidor e novas comunicações do mesmo threadMensagens = new Thread(new ThreadStart(RecebeMensagens)); threadMensagens.SetApartmentState(ApartmentState.STA); threadMensagens.Start(); }
// Envia a mensagem digitada para o servidor private void EnviaMensagem() { if (txtMensagem.Lines.Length >= 1) { if (lbUsuarios.Text != null && lbUsuarios.Text != "" && lbUsuarios.Text != this.Usuario) { pacoteEnviar = new Pacote(); pacoteEnviar.Comando = Comando.MensagemPrivada; pacoteEnviar.Usuario = this.Usuario; pacoteEnviar.UsuarioDestino = lbUsuarios.Text; pacoteEnviar.Mensagem = txtMensagem.Text; string objEnviar = JsonConvert.SerializeObject(pacoteEnviar); //var resposta = Encoding.ASCII.GetBytes(objEnviar); swEnviar.WriteLine(objEnviar); swEnviar.Flush(); txtMensagem.Lines = null; } else { pacoteEnviar = new Pacote(); pacoteEnviar.Comando = Comando.Mensagem; pacoteEnviar.Usuario = this.Usuario; pacoteEnviar.Mensagem = txtMensagem.Text; string objEnviar = JsonConvert.SerializeObject(pacoteEnviar); //var resposta = Encoding.ASCII.GetBytes(objEnviar); swEnviar.WriteLine(objEnviar); swEnviar.Flush(); txtMensagem.Lines = null; } } txtMensagem.Text = ""; }