Socket em C#
Para a cadeira de Redes de Computadores da faculdade tive que fazer um pequeno projeto no estilo Cliente-Servidor.
Usando C#, criei um exemplo bem simples onde o Cliente manda uma mensagem (string) ao Servidor e ester responde mandando outra mensagem (string do cliente em letras maiúsculas).
O Servidor:
Crie um projeto Console Application chamado Servidor. Criamos uma classe Servidor e adicionamos:
using System.Net; using System.Net.Sockets;
Agora criamos os atributos:
private const int TAMANHO_BUFFER = 10000; private int requisicoes;
O TAMANHO_BUFFER indica o tamanho máximo da mensagem recebida pelo servidor.
E requisicoes é o número de mensagens que o cliente mandou.
//mensagem que o cliente manda para o servidor private string mensagemCliente; //mensagem que o servidor manda ao cliente private string respostaServidor;
Criamos agora os Sockets:
//Socket do servidor private TcpListener servidor; //Socket do cliente private TcpClient cliente;
que são os atributos responsáveis pela troca de mensagens (comunicação).
Construtor do Servidor:
public Servidor(int porta) { this.servidor = new TcpListener(IPAddress.Any, porta); this.cliente = default(TcpClient); this.servidor.Start(); this.cliente = servidor.AcceptTcpClient(); this.requisicoes = 0; this.respostaServidor = ""; }
Instanciamos o socket do servidor passando o número da porta de comunicação eusamos o construtor default do socket cliente para criarmos uma instancia dele.
linha:
this.cliente = servidor.AcceptTcpClient();
inicia a comunicação entre o servidor e o cliente. O servidor espera o cliente se conectar a ele.
Vamos agora criar um método de troca de mensagens, onde o Servidor recebe uma mensagem do Clientee envia uma nova mensagem para este.
public void Run() { this.requisicoes++; NetworkStream netStream = cliente.GetStream(); byte[] recebido = new byte[TAMANHO_BUFFER]; //recebe a mensagem do cliente netStream.Read(recebido, 0, (int)cliente.ReceiveBufferSize); //converte bytes em string this.mensagemCliente = Encoding.ASCII.GetString(recebido); /* reduz a string deixando de fora os caracteres * adicionados durante o processo de conversão bytes->string */ this.mensagemCliente = this.mensagemCliente.Substring(0, this.mensagemCliente.IndexOf("$")); /* define a resposta do servidor * manda para o cliente a mensagem recebida * convertida em letras maiusculas */ this.respostaServidor = "Resposta do Servidor " + Convert.ToString(requisicoes) + ": " + + this.mensagemCliente.ToUpperInvariant(); Byte[] enviado = Encoding.ASCII.GetBytes(this.RespostaServidor); //envia a resposta em bytes ao cliente netStream.Write(enviado, 0, enviado.Length); netStream.Flush(); }
NetworkStream netStream = cliente.GetStream() -> habilita um canal de fluxo de dados para o Cliente.
Agora na classe Program.cs que foi criada no nosso projeto Console, adicionamos:
//indica a porta de conexão const int PORTA = 9999; //cria o servidor Servidor servidor; servidor = new Servidor(PORTA); Console.WriteLine(">> Conexão estabelecida com cliente"); while (true) { try { //executa o servidor servidor.Run(); //imprime as mensagens Console.WriteLine(">> Dados do Cliente: " + servidor.MensagemCliente); Console.WriteLine(">> Servidor envia: " + servidor.RespostaServidor); } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); } }
O while(true) faz com que o Servidor sempre receba e mande dados até o programa ser fechado.
Nosso Servidor está pronto para se conectar a um Cliente!
Cliente:
Crie um projeto Windows Forms e adicione uma Classe chamada Cliente:
Crie os atributos:
//porta de comunicação do socket const int PORTA = 9999; //tamanho máximo da mensagem recebida do cliente const int TAMANHO_BUFFER = 10000; //socket do cliente private TcpClient cliente; //mensagem que o cliente manda para o servidor private string mensagem; //mensagem que o servidor manda de volta ao cliente private string respostaServidor;
Note que é bem parecida com a classe Servidor.
Criamos o construtor:
public Cliente() { this.cliente = new TcpClient(); this.cliente.Connect("127.0.0.1", PORTA); }
Conectamos o cliente ao endereço IP 127.0.0.1, localhost, que é o endereço IP da máquina onde o Servidor está rodando, neste caso usamos o localhost porque vamos rodar o Cliente e o Servidor na mesma máquina.
Se o Servidor estivesse em outra máquina, teriamos que usar o IP dela para fazer a conexão.
Por fim, utilizaremos a porta de conexão 9999;
Criaremos o mesmo método Run que utilizamos no Servidor com a diferença de que o Cliente envia a mensagempara o Servidor para depois receber a resposta dele (o Servidor primeiro recebe a mensagem e depois envia).
public void EnviarMensagem(string mensagem) { this.mensagem = mensagem; NetworkStream servidorStream = this.cliente.GetStream(); /* adiciona um caractere especial para melhorar a * impressão da mensagem no servidor console * e converte a mensagem em um array de bytes */ byte[] saida = Encoding.ASCII.GetBytes(mensagem + "$"); //envia a mensagem ao servidor servidorStream.Write(saida, 0, saida.Length); servidorStream.Flush(); byte[] entrada = new byte[TAMANHO_BUFFER]; //recebe uma mensagem do servidor servidorStream.Read(entrada, 0, (int)this.cliente.ReceiveBufferSize); //converte a mensagem do servidor em uma string this.respostaServidor = Encoding.ASCII.GetString(entrada); }
A linha:
servidorStream.Flush();
limpa o fluxo de conexão entre o Cliente e o Servidor.
Agora na Classe Gráfica Form1 que foi criada no nosso projeto Cliente, adicionamos:
Cliente cliente = new Cliente();
E criamos o evento de troca de mensagem a partir do clique no botão Enviar, enviando ao Sevidor o conteudo do TextBox Mensagem:
private void btnEnviar_Click(object sender, EventArgs e) { cliente.EnviarMensagem(txtMensagem.Text); txtServidor.Text = ">> " + cliente.RespostaServidor; }
Nosso cliente também está pronto!
Para testar, execute o projeto Servidor e depois o Projeto Cliente.
Desafio: Que tal modificar a Classe Servidor para se conectar a mais de um Cliente ao mesmo tempo?
Até a próxima!
Tentei fazer, mas não está rodando. Só aparece o cmd do servidor e não escreve nada. Você pode me ajudar?
Thamires, você tem que rodar primeiro o programa do servidor e depois o do cliente. Tenha certeza que as portas de comunicação são as mesmas para os dois programas. Abraço.
Já tentei fazer isso, mas os arquivos estão juntos. Sou nova na área e não estou muito safa nisso. Pensei em criar dois novos projetos. Será que vai funcionar assim?