Esta pode ser uma questão muito básica, mas me confunde.
Dois soquetes conectados diferentes podem compartilhar uma porta? Estou escrevendo um servidor de aplicativos que deve ser capaz de lidar com mais de 100k conexões simultâneas e sabemos que o número de portas disponíveis em um sistema é de cerca de 60k (16 bits). Um soquete conectado é atribuído a uma nova porta (dedicada), então isso significa que o número de conexões simultâneas é limitado pelo número de portas, a menos que vários soquetes possam compartilhar a mesma porta. Então, a pergunta.
Obrigado pela ajuda antecipadamente!
Escuta TCP / HTTP nas portas: como muitos usuários podem compartilhar a mesma porta
Então, o que acontece quando um servidor escuta conexões de entrada em uma porta TCP? Por exemplo, digamos que você tenha um servidor web na porta 80. Vamos supor que seu computador tenha o endereço IP público 24.14.181.229 e a pessoa que tenta se conectar a você tem o endereço IP 10.1.2.3. Essa pessoa pode se conectar a você abrindo um soquete TCP para 24.14.181.229:80. Simples o suficiente.
Intuitivamente (e erroneamente), a maioria das pessoas presume que seja algo assim:
Isso é intuitivo, pois do ponto de vista do cliente, ele possui um endereço IP, e se conecta a um servidor em IP: PORT. Já que o cliente se conecta à porta 80, a porta dele também deve ser 80? É uma coisa sensata de se pensar, mas na verdade não é o que acontece. Se isso fosse correto, poderíamos servir apenas um usuário por endereço IP estrangeiro. Depois que um computador remoto se conecta, ele monopoliza a conexão da porta 80 para a porta 80 e ninguém mais consegue se conectar.
Três coisas devem ser entendidas:
1.) Em um servidor, um processo está escutando em uma porta. Assim que consegue uma conexão, ele passa para outro segmento. A comunicação nunca monopoliza a porta de escuta.
2.) As conexões são identificadas exclusivamente pelo sistema operacional pela seguinte 5-tupla: (local-IP, local-porta, remoto-IP, porta remota, protocolo). Se qualquer elemento da tupla for diferente, então esta é uma conexão completamente independente.
3.) Quando um cliente se conecta a um servidor, ele escolhe uma porta de origem de alta ordem aleatória e não utilizada . Dessa forma, um único cliente pode ter até ~ 64k conexões com o servidor para a mesma porta de destino.
Então, isso é realmente o que é criado quando um cliente se conecta a um servidor:
Olhando para o que realmente acontece
Primeiro, vamos usar o netstat para ver o que está acontecendo neste computador. Usaremos a porta 500 em vez de 80 (porque um monte de coisas está acontecendo na porta 80, pois é uma porta comum, mas funcionalmente não faz diferença).
Como esperado, a saída está em branco. Agora vamos iniciar um servidor web:
Agora, aqui está o resultado da execução de netstat novamente:
Portanto, agora existe um processo que está ouvindo ativamente (Estado: LISTEN) na porta 500. O endereço local é 0.0.0.0, que é o código para "ouvir todos os endereços IP". Um erro fácil de cometer é escutar apenas na porta 127.0.0.1, que só aceita conexões do computador atual. Portanto, esta não é uma conexão, isso significa apenas que um processo solicitou o bind () ao IP da porta, e esse processo é responsável por lidar com todas as conexões para essa porta. Isso sugere a limitação de que só pode haver um processo por computador ouvindo em uma porta (há maneiras de contornar isso usando a multiplexação, mas este é um tópico muito mais complicado). Se um servidor web estiver escutando na porta 80, ele não pode compartilhar essa porta com outros servidores web.
Agora, vamos conectar um usuário à nossa máquina:
Este é um script simples ( https://github.com/grokit/quickweb ) que abre um soquete TCP, envia a carga ("Carga de teste." Neste caso), espera alguns segundos e se desconecta. Executar netstat novamente enquanto isso está acontecendo exibe o seguinte:
Se você se conectar a outro cliente e executar o netstat novamente, verá o seguinte:
... ou seja, o cliente usou outra porta aleatória para a conexão. Portanto, nunca há confusão entre os endereços IP.
fonte
Essa é uma intuição comum, mas está incorreta. Um soquete conectado não está atribuído a uma porta nova / dedicada. A única restrição real que a pilha TCP deve satisfazer é que a tupla de (local_address, local_port, remote_address, remote_port) deve ser única para cada conexão de socket. Assim, o servidor pode ter muitos sockets TCP usando a mesma porta local, desde que cada um dos sockets na porta esteja conectado a um local remoto diferente.
Consulte o parágrafo "Par de soquetes" em: http://books.google.com/books?id=ptSC4LpwGA0C&lpg=PA52&dq=socket%20pair%20tuple&pg=PA52#v=onepage&q=socket%20pair%20tuple&f=false
fonte
bind()
operação precede aconnect()
operação, mesmo implicitamente.bind()
só fosse usado antes no lado do servidor.accept()?
Então, o lado do cliente também vinculará a porta específica?bind()
pode ser usado no lado do cliente antesconnect()
.Teoricamente sim. Pratique, não. A maioria dos kernels (incl. Linux) não permite um segundo
bind()
para uma porta já alocada. Não foi um remendo muito grande tornar isso permitido.Conceitualmente, devemos diferenciar entre soquete e porta . Sockets são terminais de comunicação bidirecionais, ou seja, "coisas" onde podemos enviar e receber bytes. É algo conceitual, não existe tal campo em um cabeçalho de pacote denominado "socket".
A porta é um identificador capaz de identificar um soquete. No caso do TCP, uma porta é um inteiro de 16 bits, mas também existem outros protocolos (por exemplo, em soquetes unix, uma "porta" é essencialmente uma string).
O principal problema é o seguinte: se um pacote de entrada chega, o kernel pode identificar seu soquete pelo número da porta de destino. É a forma mais comum, mas não é a única possibilidade:
Como você está trabalhando em um servidor de aplicativos, ele poderá fazer isso.
fonte
bind()
.bind()
? Eu posso imaginar, sim é bem possível, mas o fato é que tanto o WinSock quanto a API Posix usam abind()
chamada para isso, mesmo a parametrização deles é praticamente a mesma. Mesmo que uma API não tenha essa chamada, de alguma forma você precisa dizê-la de onde deseja ler os bytes de entrada .listen()
/accept()
API podem criar os sockets de uma maneira que o kernel os diferencie por suas portas de entrada. A questão do OP pode ser interpretada na forma como ele a pede essencialmente. Acho que é bastante realista, mas não é isso que sua pergunta significa literalmente.Não. Não é possível compartilhar a mesma porta em um determinado instante. Mas você pode fazer sua aplicação de forma que ela faça o acesso à porta em instantes diferentes.
fonte