Entendendo o conceito de Sockets e Portas em redes
Porta
Em uma rede, os computadores são identificados por seus endereços IP ou nomes de host, que são mapeados para esses endereços por meio do DNS. (No primeiro artigo desta série, vimos como ocorre a resolução de endereços e em que ordem as consultas são feitas.)
Saber o endereço do host de destino é apenas o primeiro passo para estabelecer uma conexão. No entanto, essa informação sozinha não é suficiente para acessar um serviço específico. É nesse ponto que entram as portas: elas funcionam como “canais” que direcionam o tráfego para a aplicação correta dentro de um host.
Características das portas
- Duas aplicações não podem escutar na mesma porta.
- Os números de porta variam de 0 a 65.535.
- Isso ocorre porque o número da porta é representado por 16 bits (2 bytes).
- Em binário, o menor valor é
0000000000000000(decimal 0) e o maior é1111111111111111(decimal 65.535).
Intervalos de portas
- Portas bem conhecidas (0–1023): usadas por serviços padrão (ex.: 80 = HTTP, 443 = HTTPS).
- Portas registradas (1024–49.151): podem ser usadas por aplicativos de terceiros.
- Portas dinâmicas ou efêmeras (49.152–65.535): utilizadas temporariamente em conexões TCP ou UDP para comunicações entre hosts.
Socket
Um socket é uma interface de software que permite a comunicação entre dois hosts por meio de uma porta específica. Ele estabelece um canal bidirecional para troca de dados.
É importante lembrar:
- A porta identifica um único processo no host.
- O socket representa uma conexão ativa com esse processo.
- Um mesmo host pode ter vários sockets ativos, enquanto cada porta está associada a apenas uma aplicação.

Exemplo: criando um socket em C#
O exemplo abaixo mostra como criar uma conexão simples usando sockets em C#, utilizando a API do Postman como servidor de teste.
static async Task Main(string[] args)
{
string server = "postman-echo.com";
int port = 80;
string path = "/get?foo1=bar1&foo2=bar2";
Socket socket = null;
IPEndPoint endpoint = null;
var host = Dns.GetHostEntry(server);
foreach (var address in host.AddressList)
{
socket = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
endpoint = new IPEndPoint(address, port);
await socket.ConnectAsync(endpoint);
if (socket.Connected)
{
Console.WriteLine("\n=== Dados sobre Socket ===");
Console.WriteLine($"Endereço local: {socket.LocalEndPoint}");
Console.WriteLine($"Endereço remoto: {socket.RemoteEndPoint}");
Console.WriteLine($"Protocolo: {socket.ProtocolType}");
Console.WriteLine($"Tipo de socket: {socket.SocketType}");
Console.WriteLine($"Família de endereços: {socket.AddressFamily}");
var message = GetRequestMessage(server, port, path);
var messageBytes = Encoding.ASCII.GetBytes(message);
var segment = new ArraySegment<byte>(messageBytes);
await socket.SendAsync(segment, SocketFlags.None);
var receiveSeg = new ArraySegment<byte>(new byte[1024], 0, 1024);
await socket.ReceiveAsync(receiveSeg, SocketFlags.None);
string receivedMessage = Encoding.ASCII.GetString(receiveSeg);
foreach (var line in receivedMessage.Split("\r\n"))
{
Console.WriteLine(line);
}
break;
}
}
socket.Disconnect(false);
socket.Dispose();
}
private static string GetRequestMessage(string server, int port, string path)
{
var message = $"GET {path} HTTP/1.1\r\n";
message += $"Host: {server}:{port}\r\n";
message += "cache-control: no-cache\r\n";
message += "\r\n";
return message;
}O código acima nos fornece informações sobre o componente socket que nos retorna o seguinte:
Endereço local: [2804:4e18:818:d1c0:a5af:9822:603b:dd18]:58280
Endereço remoto: [2606:4700:7::21d]:80
Protocolo: Tcp
Tipo de socket: Stream
Família de endereços: InterNetworkV6Perceba que definimos um tipo de socket ao criar a instância. No C# é fornecido 6 tipos, são eles:
SocketType.Stream- é usado com o protocolo TCP e fornece uma conexão confiável, bidirecional e sem erros.
SocketType.Dgram- é usado com o protocolo UDP e não garante entrega e nem integridade (padrão do protocolo UDP).
SocketType.Raw- é usado com o protocolo ICMP e IP que permite o acesso direto a protocolos de baixo nível.
SocketType.Rdm- suporta mensagens sem conexão, orientadas a mensagens, entregues de forma confiável e preserva os limites das mensagens nos dados.
SocketType.Seqpacket- fornece transferência bidirecional confiável e orientada à conexão de fluxos de bytes ordenados em uma rede.
SocketType.Unknown- específica um tipo de socket desconhecido.
Baseado no que vimos podemos dizer que uma conexão HTTP feita pelo nosso código usando o HttpClient realiza esses mesmos processos que vimos no código acima. Os processos são:
- Resolução de DNS.
- Criação de um Socket para realizar a conexão.
- Conexão TCP (3-way handshake).
- Envio da requisição HTTP.
- Recebimento da resposta HTTP.
- Fechamento ou reaproveitamento da conexão.
- Processamento da resposta.
No HttpClient a maioria dos processos são abstraídos e não precisamos realizar quase nada do que vimos ao criar o Socket.
Referências

c
Navegação
- Artigo anterior:

