UDP, Códigos em C# para Cliente e Servidor

UDP é um protocolo não confiável para transmitir dados pela internet.

"Não confiável, então porque eu deveria usá-lo?"

Como exemplo, imagine que você queira se comunicar de uma aplicação nas nuvens para o seu computador, o protocolo TCP é o mais indicado tanto para o recebimento quanto envio de dados, já que ele é bastante confiável. Mas ele não é confiável do nada, há todo um envio/reenvio/envio/reenvio/… de pacotes para assegurar que os dados cheguem de uma lado para o outro, isso acarreta em uma diminuição na taxa de transferência de tais dados. Resumindo, o TCP é bom para ser usado em controle, para dados que você não pode perder de jeito nenhum, mas não é tão bom quanto o UDP em performance, ou seja, em velocidade.

Então, se os seus dados precisam ser passados de forma rápida, mas você pode perder alguns deles sem comprometer o resultado final, use o UDP.

"Mas onde eu iria usar isso, Feodrippe?”

Eu estive brincando com o Kinect no MIC - ETEPAM por esses dias e fui tentar utilizar Sockets utilizando o TCP. O software que rodava junto ao Kinect implementava o servidor e o software cliente estava em outro computador. O cliente “perguntava” pelos dados, por exemplo, da mão esquerda do jogador e o servidor “respondia” mandando esses dados. O problema ocorreu quando eu quis atualizar meus dados do lado cliente a uma taxa de mais ou menos 20 “perguntas” por segundo (antes eram 10), o servidor simplesmente mandou dados de aquisições anteriores, ou seja, o protocolo TCP arregou, não mandou os dados da forma correta. Ainda não testei com o UDP, mas, fazendo alguns testes com os códigos colocados abaixo, vi que é bem mais rápido que o TCP (novidade…) e, pelo menos na rede Ethernet, não houve perda de dados (que bom).

Outro lugar onde você poderia usar o UDP é em dispositivos embarcados (dou valor), você poderia pegar dados de um termômetro (acelerômetro etc), por exemplo, a uma taxa de amostragem de 2000Hz (2000 amostras por segundo) e mandá-los, através de uma conexão à rede, utilizando microcontroladores tipo Arduino, tens acesso ao mundo real, feliz?. Você pode fazer o que quiser, é só querer… e estudar, oka?


 

Os códigos:


Servidor (Listener)

using System;
using System.Net.Sockets;
using System.Net;
using System.Text;

public class UdpServer
{
    static IPAddress ip;

    class UdpState
    {
        public UdpClient u;
        public IPEndPoint e;
    }

    public static void receiveCallback(IAsyncResult ar)
    {
        UdpClient u = (UdpClient)((UdpState)(ar.AsyncState)).u;
        IPEndPoint e = (IPEndPoint)((UdpState)(ar.AsyncState)).e;

        Byte[] receiveBytes = u.EndReceive(ar, ref e);
        string receiveString = Encoding.ASCII.GetString(receiveBytes);

        Console.WriteLine("Received: {0}", receiveString);

        UdpState s = new UdpState();
        s.e = e;
        s.u = u;
        u.BeginReceive(new AsyncCallback(receiveCallback), s);
    }

    public static void receiveMessages()
    {
        // Receive a message and write it to the console.
        byte[] adress = { 127, 0, 0, 1 };
        ip = new IPAddress(adress);
        IPEndPoint e = new IPEndPoint(ip, 8090);
        UdpClient u = new UdpClient(e);

        UdpState s = new UdpState();
        s.e = e;
        s.u = u;
        u.BeginReceive(new AsyncCallback(receiveCallback), s);
    }

    static void Main(string[] args)
    {
        UdpServer.receiveMessages();

        while (true)
        {}
    }

}

 

Cliente

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace UDPTestServer01
{
    class Program
    {

        static void Main(string[] args)
        {
            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 
                                  ProtocolType.Udp);

            IPAddress broadcast = IPAddress.Parse("127.0.0.1");

            byte[] sendbuf;
            IPEndPoint ep = new IPEndPoint(broadcast, 8090);

            int counter = 0;
            while (true)
            {
                Console.WriteLine(counter);
                sendbuf = Encoding.ASCII.GetBytes(Convert.ToString(counter++) + 
                                               "\t" + Convert.ToString(counter) + 
                                               "\t" + Convert.ToString(counter));
                s.SendTo(sendbuf, ep);
                Thread.Sleep(1);
            }

        }
    }
}


Boa sorte, se não funcionar… paciência, funcionou comigo, teu dia chegará!