> For the complete documentation index, see [llms.txt](https://web101.leandronsp.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://web101.leandronsp.com/internet/tcp-sockets.md).

# 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="https://1859591191-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8ipiROc4LnGxp3JLLiCL%2Fuploads%2FmMZlDIAm8s448XcLRLiD%2FScreenshot%202022-10-09%20at%2000.23.41.png?alt=media&amp;token=a93e9db3-699e-4042-ae30-fa9b753cc5ae" 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="https://1859591191-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8ipiROc4LnGxp3JLLiCL%2Fuploads%2FQunAKY2o2WthflRZOI0X%2FScreenshot%202022-10-09%20at%2000.45.44.png?alt=media&amp;token=e5c23062-41cf-40d8-9ea6-2d01a148c87b" 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="https://1859591191-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8ipiROc4LnGxp3JLLiCL%2Fuploads%2FgfAJ3tGeP7J0Ja162UGX%2FScreen-Recording-2022-10-09-at-0.gif?alt=media&amp;token=303b5e0b-fab6-48b2-bbfc-ede7984f9dce" 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**.
