Inicial > .NET > Socket em C#

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:

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:

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?

Download do Projeto

Até a próxima!

Categorias:.NET
  1. Thamires Electo
    06/05/2012 às 8:23 PM

    Tentei fazer, mas não está rodando. Só aparece o cmd do servidor e não escreve nada. Você pode me ajudar?

    • 06/05/2012 às 9:51 PM

      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.

  2. Thamires Electo
    06/06/2012 às 6:17 PM

    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?

  1. 09/15/2011 às 9:24 PM

Deixar mensagem para Thamires Electo Cancelar resposta