S é um programa servidor: digamos que é um servidor HTTP, então ele usará o número de porta bem conhecido para HTTP , que é 80. Eu o executo em um host com o endereço IP 10.0.0.4
, para que ele ouça as conexões em 10.0.0.4:80
(porque é lá que todo mundo espera encontrá-lo).
Dentro de S , criamos um soquete e vincule a esse endereço: agora, o SO sabe que as conexões estão chegando em 10.0.0.4:80
deve ser encaminhado para o meu processo S através desse socket específico.
-
saída netstat quando o socket está ligado:
$ netstat --tcp -lan Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
NB. o endereço local é todos os zeros porque S não se importa como seus clientes o acessam
Uma vez que S tenha esse limite de soquete, ele aceita conexões - cada vez que um novo cliente se conecta, accept
retorna um novo socket, que é específico para esse cliente
-
saída netstat quando uma conexão é aceita:
$ netstat --tcp -lan Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN tcp 0 0 10.0.0.4:80 10.0.0.5:55715 ESTABLISHED
-
10.0.0.4:80
representa o final da conexão de S e está associado ao soquete retornado poraccept
-
10.0.0.5:55715
é o final da conexão do cliente e está associado ao soquete que o cliente transmitiu para conectar a>. A porta do cliente não é usada para nada, exceto pacotes de roteamento nesta conexão TCP para o processo certo: é atribuído aleatoriamente pelo kernel do cliente a partir do intervalo de portas efêmeras.
-
Agora, o S pode continuar aceitando mais conexões de clientes ... cada um receberá seu próprio soquete, cada soquete será associado a uma única conexão TCP e cada conexão terá um único endereço remoto. S rastreará o estado do cliente (se houver algum) associando-o ao soquete.
Então, aproximadamente:
- o endereço IP é para roteamento entre hosts na rede
- a porta é para roteamento para o soquete correto no host
- Eu quase disse processo correto , mas na verdade é possível ter vários processos (geralmente filhos) todos aceitando no mesmo soquete ...
- no entanto, cada vez que uma das chamadas
accept
simultâneas é retornada, ela o faz somente em um processo, cada soquete da conexão de entrada é exclusivo para uma instância do servidor
- o soquete é o objeto que um processo usa para conversar com o SO sobre uma determinada conexão, muito parecido com um descritor de arquivo
- como mencionado nos comentários, há muitos outros usos para sockets que não usam portas: por exemplo socketpair cria um par de soquetes conectados juntos que não têm nenhum esquema de endereçamento - a única maneira de usar esse pipe é sendo o processo que chama
socketpair
, sendo um filho desse processo e herdando um, ou sendo explicitamente passado um dos soquetes desse processo
- como mencionado nos comentários, há muitos outros usos para sockets que não usam portas: por exemplo socketpair cria um par de soquetes conectados juntos que não têm nenhum esquema de endereçamento - a única maneira de usar esse pipe é sendo o processo que chama