Pelo que entendi, é isso que acontece quando um cliente faz uma solicitação de conexão:
- O servidor será vinculado a um número de porta específico. O número da porta está sempre vinculado a um processo de atendimento. Como apenas o servidor está escutando as conexões de entrada, não precisamos vincular no lado do cliente
- O servidor continuará ouvindo esse número da porta.
- O cliente enviará uma
connect()
solicitação. - O servidor aceitará a solicitação usando
accept()
. Assim que o servidor aceita a solicitação do cliente, o kernel aloca um número de porta aleatório para o servidor por mais temposend()
ereceive()
, como o mesmo número de porta no servidor não pode ser usado para enviar e ouvir, e a porta anterior ainda está ouvindo novas conexões
Dado tudo isso, como o servidor descobre em qual porta o cliente está recebendo? Sei que o cliente enviará segmentos TCP com uma porta de origem e uma porta de destino; portanto, o servidor usará a porta de origem desse segmento como porta de destino, mas que função o servidor chama para descobrir sobre essa porta? É isso accept()
?
Respostas:
Faz parte do cabeçalho TCP (ou UDP, etc.), no pacote. Portanto, o servidor descobre porque o cliente diz. É semelhante a como ele descobre o endereço IP do cliente (que faz parte do cabeçalho IP).
Por exemplo, todo pacote TCP inclui um cabeçalho IP (com IP de origem, IP de destino e protocolo [TCP], pelo menos). Depois, há um cabeçalho TCP (com porta de origem e destino, além de mais).
Quando o kernel recebe um pacote SYN (o início de uma conexão TCP) com um IP remoto de 10.11.12.13 (no cabeçalho IP) e uma porta remota de 12345 (no cabeçalho TCP), ele conhece o IP e a porta remotos . Ele envia de volta um SYN | ACK. Se receber um ACK de volta, a
listen
chamada retornará um novo soquete, configurado para essa conexão.Um soquete TCP é identificado exclusivamente pelos quatro valores (IP remoto, IP local, porta remota, porta local). Você pode ter várias conexões / soquetes, desde que pelo menos um deles seja diferente.
Normalmente, a porta local e o IP local serão os mesmos para todas as conexões com um processo do servidor (por exemplo, todas as conexões com o sshd estarão em local-ip: 22). Se uma máquina remota fizer várias conexões, cada uma usará uma porta remota diferente. Portanto, tudo, menos a porta remota, será a mesma, mas tudo bem - apenas um dos quatro deve ser diferente.
Você pode usar, por exemplo, wirehsark para ver o pacote, e ele rotulará todos os dados para você. Aqui está a porta de origem destacada (observe que está destacada no pacote decodificado, bem como o dump hexadecimal na parte inferior):
fonte
write
(etc.) vão para o lugar certo.A "solicitação de conexão (
connect()
normalmente, a chamada do sistema do programa cliente ) causa um handshake de três vias . O primeiro pacote do handshake de três vias (do cliente para o servidor) tem o sinalizador SYN definido e inclui o número da porta TCP que o programa cliente kernel atribui a ele.Você pode ver isso em um artigo sobre pacotes Nmap vs Natural SYN . A decodificação de pacotes Nmap SYN possui a frase "source.60058> dest.22". A decodificação "legítimo pacote SYN" contém a frase "source.35970> dest.80". Os dois pacotes SYN informam ao kernel remoto que os pacotes são da porta TCP 60058 e da porta 35970, respectivamente.
fonte
getpeername()
deve permitir que você faça isso em qualquer soquete aberto. Aaccept()
chamada do sistema que o código do servidor deve usar para obter um descritor de arquivo de soquete para se comunicar com o cliente possui um parâmetro ("sockaddr" nas minhas páginas de manual) que contém o endereço IP e o número da porta TCP do cliente em potencial.O soquete TCP é um soquete orientado para o fluxo. Os dois descritores de soquete (pertencentes a você e seu par) estão conectados de maneira confiável. Então você não precisa se preocupar com a porta do cliente - basta escrever o seu descritor de soquete!
Além disso, sinta-se à vontade para o getsockname (2) se você realmente quiser saber (talvez para registrar).
fonte
A conexão é definida por uma tupla (IP de origem, porta de origem, IP de destino, porta de destino). As respostas vão ao contrário.
fonte