# TCP Sockets

**TCP**, ou *Transmission Control Protocol*, é uma abstração de **stream sockets** na camada TCP/IP da Internet. Por se no formato stream, há a garantia de entrega da mensagem na *ordem correta*.

Assim como UNIX sockets, também podemos criar TCP sockets com `netcat`. Inclusive o padrão do netcat é TCP, portanto basta removermos a opção `-U` dos exemplos que criamos anteriormente e pronto, temos um socket TCP.

<pre class="language-bash"><code class="lang-bash"><strong>## Server
</strong><strong>$ nc -lv /tmp/server.sock
</strong><strong>nc: getaddrinfo: Servname not supported for ai_socktype
</strong></code></pre>

Uh, oh...não conseguimos criar o server no socket `server.sock` com TCP.&#x20;

Para entender este erro, vamos primeiro simular como seria um **cliente remoto**, ou seja, em outro computador, conectando neste socket.&#x20;

*Ps: para efeitos didáticos, vamos fazer todos os exemplos no mesmo computador. Com TCP funciona na mesma, é como se tivéssemos em computadores diferentes.*

```bash
## Client
$ nc -v /tmp/server.sock
nc: missing port number
```

Vamos por ora *ignorar* a mensagem de erro. Repare o problema neste comando. O cliente precisa **saber o caminho do socket no servidor** remoto. Isto pode trazer *problemas de segurança* graves, pois um cliente conhecer o caminho do socket **abre caminhos para possíveis ataques** ao servidor.

<figure><img src="/files/SNR6aaQu10C7W2xdstIc" alt=""><figcaption></figcaption></figure>

Por isto é **obrigatório** que o client informe o *número da porta*. Mas que porta? O quê é uma porta neste contexto de TCP/networking?

### Portas de rede

**Porta** é um conceito em redes de computadores que permite abstrair o caminho de um socket, mais precisamente de um **processo em execução no sistema operacional**.&#x20;

A forma que uma porta é associada e um processo é através de um conceito parecido com *file descriptors*, que são **socket descriptors**.

<figure><img src="/files/RWUNldb4eAdf6740ac0Q" alt=""><figcaption></figcaption></figure>

### Conexão cliente-servidor

Como agora sabemos que um socket TCP precisa do número da porta, basta iniciarmos o comando `netcat` com o número de uma porta que não esteja sendo utilizada, ao invés do nome do socket.

```bash
## Server
$ nc -lv 8080
Listening on 0.0.0.0 8080
```

* `-l`: o server ficará à escuta de conexões na porta 8080
* `-v`: modo verboso

Nice! Temos um TCP socket rodando na porta *8080* do computador. E como podemos confirmar isto? Com o comando `lsof`:

```bash
$ lsof -i tcp:3000
COMMAND  PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
nc      1113 root    3u  IPv4 7228577      0t0  TCP *:8080 (LISTEN)
```

Podemos ver que o comando `nc`, de PID `1113`, está no modo **LISTEN TCP** na porta **8080**.&#x20;

Agora, vamos ao lado do cliente:

```bash
## Client
$ nc -v localhost 8080
Connection to localhost (127.0.0.1) 8080 port [tcp/*] succeeded!
```

Note que o comando `nc`, caso seja utilizado como client, precisa informar **2 argumentos**:

1. endereço do server, neste caso, utilizamos o próprio **localhost** mas poderia ser qualquer IP público da rede
2. número da porta onde o server está à escuta, neste caso, **8080**

<figure><img src="/files/WFbN7c7zTwJ9wrnj2QWe" alt=""><figcaption></figcaption></figure>

Na interação acima, repare que assim que o cliente conecta no server, é mostrada a mensagem `Connection received on localhost 46216`.&#x20;

Isto porque, pela característica **full-duplex** como vimos com 2 named pipes e UNIX sockets, os sockets TCP também estabelecem *outro socket* para leitura do cliente, neste caso, **outra porta de rede**.&#x20;

Inclusive dá pra confirmar verificando todos os processos interagindo com a porta 8080:

```bash
$ lsof -i tcp:8080
COMMAND  PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
nc      1280 root    3u  IPv4 7280841      0t0  TCP *:8080 (LISTEN)
nc      1280 root    4u  IPv4 7280100      0t0  TCP localhost:8080->localhost:46216 (ESTABLISHED)
nc      1283 root    3u  IPv4 7280954      0t0  TCP localhost:46216->localhost:8080 (ESTABLISHED)
```

Com isto, podemos concluir que:

* há um *file descriptor* (3u) criado para o socket do server e também as mensagens dentro da conexão TCP que o cliente envia para o server, **da porta 46216 para a porta 8080**
* há outro *file descriptor* (4u) para representar as mensagens dentro da conexão TCP que o server envia de volta para o cliente, **da porta 8080 para a porta 46216**

É tudo sobre **file descriptors**!

### Resumo

Esta seção apresentou a funcionalidade de **TCP sockets**, bem como sua similaridade com UNIX *stream* sockets.&#x20;

A seguir, vamos explorar como trabalhar com sockets de internet que utilizam *datagram*, os **sockets UDP**.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://web101.leandronsp.com/internet/tcp-sockets.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
