C# - Usando classes para a programação com a web (.NET Core) - V


Hoje vamos continuar  a apresentar algumas classes que facilitam a programação para web na linguagem C#.


Continuando a quarta parte do artigo vamos tratar do protocolo TCP  na linguagem C# na .NET Core.
 

 

Usando TCP

 

O protocolo HTTP é baseado no Protocolo TCP - Protocolo de Controle de Transmissão. Com o TCP, o cliente precisa primeiro para abrir uma conexão com o servidor antes de enviar comandos usando o HTTP.

As classes HttpClient e WebListener ocultam os detalhes do protocolo HTTP. Quando você está usando as classes TCP e você envia requisições HTTP, e precisa saber mais sobre o protocolo HTTP.

 

A classe TcpClient
 

A classe TcpClient solicita dados de um recurso da Internet usando o TCP. Os métodos e as propriedades de TcpClient abstraem os detalhes para criar um Socket para solicitar e receber dados usando o TCP. Como a conexão com o dispositivo remoto é representada como um fluxo (stream), os dados podem ser lidos e gravados com técnicas de manipulação de fluxo do .NET Framework.

 

O protocolo TCP estabelece uma conexão com um ponto de extremidade remoto e, em seguida, usar essa conexão para enviar e receber pacotes de dados. O TCP é responsável por garantir que os pacotes de dados são enviados para o ponto de extremidade e montados na ordem correta quando chegarem.

Para estabelecer uma conexão TCP, você deve saber o endereço do dispositivo de rede que hospeda o serviço necessário e saber a porta TCP usada pelo serviço para se comunicar. A IANA (Internet Assigned Numbers Authority) define os números da porta de serviços comuns. Os serviços que não estão na lista da IANA podem ter números de porta no intervalo de 1.024 a 65.535 que estão disponíveis para uso.

 

A classe TcpListner

 

A classe TcpListener  é usada para monitorar uma porta TCP para requisições de entrada e, em seguida, criar um Socket ou um TcpClient que gerencia a conexão com o cliente.


O método Start habilita a escuta e o método Stop desabilita a escuta na porta. O método AcceptTcpClient  aceita solicitações de conexão de entrada e cria um TcpClient para manipular a solicitação e o método AcceptSocket aceita solicitações de conexão de entrada e cria um Socket para manipular a solicitação.

 

Exemplo prático

 

Vamos criar um projeto .NET Core tipo Console no VS 2017 Community chamado NETCore_TCP1.

 

Vamos criar uma aplicação Console que envia uma requisição HTTP para um servidor web usando a classe TcpClient, e, para isso vamos ter que usar recursos do protocolo HTTP.


Nossa aplicação vai aceitar argumentos da linha de comando para passar o nome do servidor web e a seguir vamos realizar uma requisição para o servidor que vai retornar uma string que vamos tratar usando a propriedade Result de Task:

 

Na aplicação console abra o arquivo Program e inclua o código abaixo:

 

using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace NETCore_TCP1
{
    class Program
    {
        private const int ReadBufferSize = 1024;
        private const string hostname = "microsoft.com";

        static void Main(string[] args)
        {
            Task<string> t1 = RequestHtmlAsync(hostname);
            Console.WriteLine(t1.Result);
            Console.ReadLine();
        }
        public static async Task<string> RequestHtmlAsync(string hostname)
        {
            try
            {
                using (var client = new TcpClient())
                {
                    await client.ConnectAsync(hostname, 80);
                    NetworkStream stream = client.GetStream();
                    string header = "GET / HTTP/1.1\r\n" + 
                                          $"Host: {hostname}:80\r\n" + 
                                          "Connection: close\r\n" + "\r\n";
                    byte[] buffer = Encoding.UTF8.GetBytes(header);
                    await stream.WriteAsync(buffer, 0, buffer.Length);
                    await stream.FlushAsync();
                    var ms = new MemoryStream();
                    buffer = new byte[ReadBufferSize];
                    int read = 0;
                    do
                    {
                        read = await stream.ReadAsync(buffer, 0, ReadBufferSize);
                        ms.Write(buffer, 0, read);
                        Array.Clear(buffer, 0, buffer.Length);
                    } while (read > 0);
                    ms.Seek(0, SeekOrigin.Begin);
                    var reader = new StreamReader(ms);
                    return reader.ReadToEnd();
                }
            }
            catch
            {
                throw;
            }
        }
    }
}

 

Vamos entender o código acima:
 

1- Instanciamos um objeto TcpClient;

2- Usando o método ConnectAsync fazemos uma conexão TCP com o host informado na porta 80

3- Recuperamos um stream (fluxo) para ler e gravar usando essa conexão usando  client.GetStream();

 

Podemos agora usar o stream para escrever a requisição para servidor e ler a resposta. O HTTP é um protocolo baseado em texto, por isso é fácil definir uma requisição em uma string.

 

Para fazer uma requisição com o servidor o header define o método GET seguido do caminho da URL e do texto 'HTTP/ 1.1'

 

A seguir definimos o header Host com o nome do Host e o número da porta e depois definimos o header da Connection.

 

Normalmente, com o cabeçalho Connection, o cliente requisita Keep-alive para perguntar ao servidor para manter a conexão aberta, pois o cliente espera fazer mais requisições.

 

Aqui estamos apenas fazendo um único pedido para o servidor, de modo que o servidor deve fechar a conexão, assim close é definido para o Header da conexão.

 

Para finalizar as informações do cabeçalho, adicionamos uma linha vazia à requisição usando \r\n.

 

As informações de cabeçalho são enviadas com codificação UTF-8 chamando o método WriteAsync da classe
NetworkStream. Para enviar imediatamente o buffer para o servidor, o método FlushAsync é chamado,  caso contrário, os dados podem ser mantidos no cache local.

 

Agora podemos continuar o processo lendo a resposta do servidor. Como não sabemos o tamanho da resposta é o
criamos um MemoryStream que cresce dinamicamente. A resposta do servidor é temporariamente gravada em um array de bytes usando o método ReadAsync, e o conteúdo desse array de bytes é adicionado ao MemoryStream.

Depois que todos os dados são lidos no servidor, um StreamReader assume o controle para ler os dados do stream em uma string retornando ao chamador.

   

Executando programa iremos obter:


 

Vemos acima a resposta obtida para a conexão com o servidor microsoft.com na porta 80.
 

Na próxima parte do artigo vamos criar um Servidor usando sockets.

 

Pegue o projeto completo aqui:   NETCore_TCP1.zip


"E tu, ó menino, serás chamado profeta do Altíssimo, Porque hás de ir ante a face do Senhor, a preparar os seus caminhos;
Para dar ao seu povo conhecimento da salvação, Na remissão dos seus pecados;
Pelas entranhas da misericórdia do nosso Deus, Com que o oriente do alto nos visitou;"
Lucas 1:76-78

 

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?


Referências:


José Carlos Macoratti