Soquete Unix - Funções Principais

Este capítulo descreve as funções de soquete centrais necessárias para escrever um cliente e servidor TCP completo.

O diagrama a seguir mostra a interação completa entre cliente e servidor -

A função de soquete

Para realizar E / S de rede, a primeira coisa que um processo deve fazer é chamar a função de soquete, especificando o tipo de protocolo de comunicação desejado e família de protocolo, etc.

#include <sys/types.h>
#include <sys/socket.h>

int socket (int family, int type, int protocol);

Esta chamada retorna um descritor de socket que você pode usar em chamadas de sistema posteriores ou -1 em caso de erro.

Parâmetros

family - Ele especifica a família do protocolo e é uma das constantes mostradas abaixo -

Família Descrição
AF_INET Protocolos IPv4
AF_INET6 Protocolos IPv6
AF_LOCAL Protocolos de domínio Unix
AF_ROUTE Encaminhando Sockets
AF_KEY Tomada Ket

Este capítulo não cobre outros protocolos, exceto IPv4.

type- Especifica o tipo de socket que você deseja. Pode assumir um dos seguintes valores -

Tipo Descrição
SOCK_STREAM Tomada de fluxo
SOCK_DGRAM Soquete de datagrama
SOCK_SEQPACKET Soquete de pacote sequenciado
SOCK_RAW Soquete cru

protocol - O argumento deve ser definido para o tipo de protocolo específico fornecido abaixo, ou 0 para selecionar o padrão do sistema para a combinação dada de família e tipo -

Protocolo Descrição
IPPROTO_TCP Protocolo de transporte TCP
IPPROTO_UDP Protocolo de transporte UDP
IPPROTO_SCTP Protocolo de transporte SCTP

A função de conexão

A função de conexão é usada por um cliente TCP para estabelecer uma conexão com um servidor TCP.

#include <sys/types.h>
#include <sys/socket.h>

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

Esta chamada retorna 0 se se conectar com sucesso ao servidor, caso contrário, retorna -1 em caso de erro.

Parâmetros

  • sockfd - É um descritor de socket retornado pela função de socket.

  • serv_addr - É um ponteiro para struct sockaddr que contém o endereço IP e a porta de destino.

  • addrlen - Defina-o como sizeof (struct sockaddr).

A função bind

A função bind atribui um endereço de protocolo local a um socket. Com os protocolos da Internet, o endereço do protocolo é a combinação de um endereço IPv4 de 32 bits ou um endereço IPv6 de 128 bits, junto com um número de porta TCP ou UDP de 16 bits. Esta função é chamada apenas pelo servidor TCP.

#include <sys/types.h>
#include <sys/socket.h>

int bind(int sockfd, struct sockaddr *my_addr,int addrlen);

Esta chamada retorna 0 se se conectar com sucesso ao endereço, caso contrário, retorna -1 em caso de erro.

Parâmetros

  • sockfd - É um descritor de socket retornado pela função de socket.

  • my_addr - É um ponteiro para struct sockaddr que contém o endereço IP local e a porta.

  • addrlen - Defina-o como sizeof (struct sockaddr).

Você pode colocar seu endereço IP e sua porta automaticamente

Um valor 0 para o número da porta significa que o sistema escolherá uma porta aleatória e o valor INADDR_ANY para o endereço IP significa que o endereço IP do servidor será atribuído automaticamente.

server.sin_port = 0;  		     
server.sin_addr.s_addr = INADDR_ANY;

NOTE- Todas as portas abaixo de 1024 são reservadas. Você pode definir uma porta acima de 1024 e abaixo de 65535, a menos que sejam usadas por outros programas.

A função de escuta

A função de escuta é chamada apenas por um servidor TCP e executa duas ações -

  • A função de escuta converte um soquete não conectado em um soquete passivo, indicando que o kernel deve aceitar solicitações de conexão de entrada direcionadas a este soquete.

  • O segundo argumento para esta função especifica o número máximo de conexões que o kernel deve enfileirar para este socket.

#include <sys/types.h>
#include <sys/socket.h>

int listen(int sockfd,int backlog);

Esta chamada retorna 0 em caso de sucesso, caso contrário, retorna -1 em caso de erro.

Parâmetros

  • sockfd - É um descritor de socket retornado pela função de socket.

  • backlog - É o número de conexões permitidas.

A função aceitar

A função de aceitação é chamada por um servidor TCP para retornar a próxima conexão concluída da frente da fila de conexão concluída. A assinatura da chamada é a seguinte -

#include <sys/types.h>
#include <sys/socket.h>

int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);

Esta chamada retorna um descritor não negativo em caso de sucesso, caso contrário, retorna -1 em caso de erro. O descritor retornado é considerado um descritor de socket do cliente e todas as operações de leitura e gravação serão feitas neste descritor para se comunicar com o cliente.

Parâmetros

  • sockfd - É um descritor de socket retornado pela função de socket.

  • cliaddr - É um ponteiro para struct sockaddr que contém o endereço IP e a porta do cliente.

  • addrlen - Defina-o como sizeof (struct sockaddr).

A função de envio

A função de envio é usada para enviar dados através de soquetes de fluxo ou soquetes de datagrama CONECTADOS. Se você quiser enviar dados através de soquetes de datagrama UNCONNECTED, você deve usar a função sendto ().

Você pode usar a chamada de sistema write () para enviar dados. Sua assinatura é a seguinte -

int send(int sockfd, const void *msg, int len, int flags);

Esta chamada retorna o número de bytes enviados, caso contrário, retornará -1 em caso de erro.

Parâmetros

  • sockfd - É um descritor de socket retornado pela função de socket.

  • msg - É um ponteiro para os dados que você deseja enviar.

  • len - É o comprimento dos dados que você deseja enviar (em bytes).

  • flags - Está definido como 0.

A função recv

A função recv é usada para receber dados por meio de soquetes de fluxo ou soquetes de datagrama CONECTADOS. Se você deseja receber dados através de sockets de datagrama UNCONNECTED, você deve usar recvfrom ().

Você pode usar a chamada de sistema read () para ler os dados. Esta chamada é explicada no capítulo de funções auxiliares.

int recv(int sockfd, void *buf, int len, unsigned int flags);

Esta chamada retorna o número de bytes lidos no buffer, caso contrário, retornará -1 em caso de erro.

Parâmetros

  • sockfd - É um descritor de socket retornado pela função de socket.

  • buf - É o buffer para ler as informações.

  • len - É o comprimento máximo do buffer.

  • flags - Está definido como 0.

A função sendto

A função sendto é usada para enviar dados através de sockets de datagramas UNCONNECTED. Sua assinatura é a seguinte -

int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);

Esta chamada retorna o número de bytes enviados, caso contrário, retorna -1 em caso de erro.

Parâmetros

  • sockfd - É um descritor de socket retornado pela função de socket.

  • msg - É um ponteiro para os dados que você deseja enviar.

  • len - É o comprimento dos dados que você deseja enviar (em bytes).

  • flags - Está definido como 0.

  • to - É um ponteiro para struct sockaddr para o host para onde os dados devem ser enviados.

  • tolen - Está definido como sizeof (struct sockaddr).

A função recvfrom

A função recvfrom é usada para receber dados de soquetes de datagrama UNCONNECTED.

int recvfrom(int sockfd, void *buf, int len, unsigned int flags struct sockaddr *from, int *fromlen);

Esta chamada retorna o número de bytes lidos no buffer, caso contrário, retorna -1 em caso de erro.

Parâmetros

  • sockfd - É um descritor de socket retornado pela função de socket.

  • buf - É o buffer para ler as informações.

  • len - É o comprimento máximo do buffer.

  • flags - Está definido como 0.

  • from - É um ponteiro para struct sockaddr para o host onde os dados devem ser lidos.

  • fromlen - Está definido como sizeof (struct sockaddr).

A função de fechamento

A função close é usada para fechar a comunicação entre o cliente e o servidor. Sua sintaxe é a seguinte -

int close( int sockfd );

Esta chamada retorna 0 em caso de sucesso, caso contrário, retorna -1 em caso de erro.

Parâmetros

  • sockfd - É um descritor de socket retornado pela função de socket.

A função de desligamento

A função de desligamento é usada para fechar normalmente a comunicação entre o cliente e o servidor. Esta função oferece mais controle em comparação com a função de fechamento . A seguir está a sintaxe de desligamento -

int shutdown(int sockfd, int how);

Esta chamada retorna 0 em caso de sucesso, caso contrário, retorna -1 em caso de erro.

Parâmetros

  • sockfd - É um descritor de socket retornado pela função de socket.

  • how - Coloque um dos números -

    • 0 - indica que o recebimento não é permitido,

    • 1 - indica que o envio não é permitido e

    • 2- indica que o envio e o recebimento não são permitidos. Quando how é definido como 2, é a mesma coisa que close ().

A função de seleção

A função de seleção indica qual dos descritores de arquivo especificados está pronto para leitura, pronto para gravação ou tem uma condição de erro pendente.

Quando um aplicativo chama recv ou recvfrom , ele é bloqueado até que os dados cheguem a esse soquete. Um aplicativo pode estar realizando outro processamento útil enquanto o fluxo de dados de entrada está vazio. Outra situação é quando um aplicativo recebe dados de vários soquetes.

Chamar recv ou recvfrom em um soquete que não possui dados em sua fila de entrada impede a recepção imediata de dados de outros soquetes. A chamada de função select resolve este problema permitindo que o programa faça polling de todos os identificadores de socket para ver se eles estão disponíveis para operações de leitura e escrita sem bloqueio.

A seguir está a sintaxe de select -

int select(int  nfds, fd_set  *readfds, fd_set  *writefds, fd_set *errorfds, struct timeval *timeout);

Esta chamada retorna 0 em caso de sucesso, caso contrário, retorna -1 em caso de erro.

Parâmetros

  • nfds- Especifica a gama de descritores de arquivo a serem testados. A função select () testa os descritores de arquivo no intervalo de 0 a nfds-1

  • readfds- Ele aponta para um objeto do tipo fd_set que, na entrada, especifica os descritores de arquivo a serem verificados para leitura, e na saída, indica quais descritores de arquivo estão prontos para ler. Pode ser NULL para indicar um conjunto vazio.

  • writefds- Ele aponta para um objeto do tipo fd_set que na entrada, especifica os descritores de arquivo a serem verificados para estarem prontos para escrever, e na saída, indica quais descritores de arquivo estão prontos para escrever. Pode ser NULL para indicar um conjunto vazio.

  • exceptfds- Ele aponta para um objeto do tipo fd_set que, na entrada, especifica os descritores de arquivo a serem verificados quanto a condições de erro pendentes e na saída indica quais descritores de arquivo têm condições de erro pendentes. Pode ser NULL para indicar um conjunto vazio.

  • timeout- Ele aponta para uma estrutura de tempo que especifica por quanto tempo a chamada de seleção deve pesquisar os descritores para uma operação de E / S disponível. Se o valor de tempo limite for 0, então select irá retornar imediatamente. Se o argumento de tempo limite for NULL, então select irá bloquear até que pelo menos um arquivo / identificador de socket esteja pronto para uma operação de E / S disponível. Caso contrário, o select retornará após a quantidade de tempo no tempo limite ter decorrido OU quando pelo menos um descritor de arquivo / soquete estiver pronto para uma operação de E / S.

O valor de retorno de select é o número de identificadores especificados nos conjuntos de descritores de arquivo que estão prontos para E / S. Se o limite de tempo especificado pelo campo de tempo limite for atingido, selecione o retorno 0. As seguintes macros existem para manipular um conjunto de descritores de arquivo -

  • FD_CLR(fd, &fdset)- Limpa o bit para o descritor de arquivo fd no conjunto de descritores de arquivo fdset.

  • FD_ISSET(fd, &fdset)- Retorna um valor diferente de zero se o bit para o descritor de arquivo fd é definido no conjunto de descritores de arquivo apontado por fdset , e 0 caso contrário.

  • FD_SET(fd, &fdset) - Define o bit para o descritor de arquivo fd no descritor de arquivo definido fdset.

  • FD_ZERO(&fdset) - Inicializa o conjunto de descritores de arquivo fdset para ter zero bits para todos os descritores de arquivo.

O comportamento dessas macros é indefinido se o argumento fd for menor que 0 ou maior ou igual a FD_SETSIZE.

Exemplo

fd_set fds;

struct timeval tv;

/* do socket initialization etc.
tv.tv_sec = 1;
tv.tv_usec = 500000;

/* tv now represents 1.5 seconds */
FD_ZERO(&fds);

/* adds sock to the file descriptor set */
FD_SET(sock, &fds); 

/* wait 1.5 seconds for any data to be read from any single socket */
select(sock+1, &fds, NULL, NULL, &tv);

if (FD_ISSET(sock, &fds)) {
   recvfrom(s, buffer, buffer_len, 0, &sa, &sa_len);
   /* do something */
}
else {
   /* do something else */
}