listen() - Tem alguém me
chamando?
Hora de mudar um pouco o rumo da prosa. E se você
não quiser se conectar a um host. Digamos que você
queira esperar por conexões remotas e tratá-las de
alguma forma. É um processo de dois passos: primeiro
você escuta(listen()), e então aceita (accept()) a
conexão.
A chamada listen() é muito simples, mas requer um
pouco de explicação:
int listen( int sockfd, int backlog);
sockfd é o já conhecido descritor de socket da
chamada socket(). backlog é o número de
conexões permitidas. O que isso significa? Bem , as
conexões ficarão na fila (queue) até que
você as aceite(accept()) e isto é o limite de
quantas conexões poderão ficar na fila. A maioria
dos sistmas limita este número para cerca de 20, mas
você pode tranquilamente usar 5 ou 10.
Novamente, como sempre, listen(0 retorna -1 em caso de
erro e seta errno.
Bem, como você deve ter imaginado, precisamos chamar
bind() antes de listen() ou o kernel irá escutar em uma
porta remota. Então se você for escutar por
conexões remotas, a sequência de chamadas de
sistema que você vai executar é:
socket();
bind();
listen();
/* accept() vem aqui */
Eu vou deixar assim ao invés de código fonte,
já que é bastante elucidativo.(O código na
seção accept() abaixo. é mais completo.)A
parte mais importante da coisa é a chamada accept().
4.5. accept() - "Obrigado por chamar a porta
3490."
Prepare-se - a chamada accept() é um tanto estranha!
O que vai acontecer é o seguinte: alguém em algum
lugar bem distante vai tentar se conectar(connect()) a sua
máquina na porta em que você estiver
ouvindo(listen()). Está conexão vai ficar na fila
(queue) esperando ser aceita(accept()). Você chama
accept() e diz para retornar a conexão pendente. A
seguir você vai ter um descritor socket novinho para
usar nessa conexão. Você ,de uma hora pra outra,
tem duas conexões pelo preço de uma! A original
ainda está ouvindo na porta especificada e a outra
está pronta para enviar(send()) e receber (recv()).
A chamada é da seguinte forma:
int accept (int sockfd, void *addr, int *addrlen);
sockfd, bem não vou ser repetitivo. addr será
geralmente um ponteiro para um struct sockaddr_in. Aqui
é onde a informação sobre a conexão vai
ficar( e com isso você pode determinar qual host
está chamando de qual porta.) addrlen é um
variável inteira local que deve ser setada para
sizeof(struct sockaddr_in) antes que seu endereço seja
passado para accept(). accept() não colocará mais
bytes que isto em addr. Se colocar menos, irá mudar o
valor de addrlen para refletir essa mudança.
Adivinha? accept() retorna -1 e o resto você já
deve saber.