Perl - Programação de Soquete

O que é um soquete?

Socket é um mecanismo Berkeley UNIX para criar uma conexão duplex virtual entre diferentes processos. Posteriormente, isso foi transferido para todos os sistemas operacionais conhecidos, permitindo a comunicação entre sistemas geográficos em execução em diferentes sistemas operacionais. Se não fosse pelo soquete, a maior parte da comunicação de rede entre os sistemas nunca teria acontecido.

Olhando mais de perto; um sistema de computador típico em uma rede recebe e envia informações conforme desejado pelos vários aplicativos em execução. Essas informações são encaminhadas para o sistema, uma vez que um endereço IP exclusivo é designado a ele. No sistema, essa informação é fornecida aos aplicativos relevantes, que escutam em portas diferentes. Por exemplo, um navegador da Internet escuta na porta 80 as informações recebidas do servidor da web. Também podemos escrever nossos aplicativos personalizados que podem ouvir e enviar / receber informações em um número de porta específico.

Por enquanto, vamos resumir que um soquete é um endereço IP e uma porta, permitindo a conexão para enviar e receber dados em uma rede.

Para explicar o conceito de socket mencionado acima, tomaremos um exemplo de Programação Cliente - Servidor usando Perl. Para completar uma arquitetura cliente-servidor, teríamos que seguir os seguintes passos -

Para criar um servidor

  • Crie um soquete usando socket ligar.

  • Ligue o soquete a um endereço de porta usando bind ligar.

  • Ouça o soquete no endereço da porta usando listen ligar.

  • Aceitar conexões de cliente usando accept ligar.

Para criar um cliente

  • Crie um soquete com socket ligar.

  • Conecte (o soquete) ao servidor usando connect ligar.

O diagrama a seguir mostra a sequência completa das chamadas usadas pelo cliente e servidor para se comunicarem -

Chamadas de soquete do lado do servidor

A chamada socket ()

o socket()chamada é a primeira chamada para estabelecer uma conexão de rede está criando um soquete. Esta chamada tem a seguinte sintaxe -

socket( SOCKET, DOMAIN, TYPE, PROTOCOL );

A chamada acima cria um SOCKET e outros três argumentos são inteiros que devem ter os seguintes valores para conexões TCP / IP.

  • DOMAINdeve ser PF_INET. Provavelmente são 2 no seu computador.

  • TYPE deve ser SOCK_STREAM para conexão TCP / IP.

  • PROTOCOL deveria estar (getprotobyname('tcp'))[2]. É o protocolo específico, como o TCP, a ser falado no soquete.

Portanto, a chamada de função de soquete emitida pelo servidor será algo assim -

use Socket     # This defines PF_INET and SOCK_STREAM

socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2]);

A chamada bind ()

Os sockets criados pela chamada socket () são inúteis até que sejam vinculados a um nome de host e um número de porta. O servidor usa o seguintebind() para especificar a porta na qual eles aceitarão conexões dos clientes.

bind( SOCKET, ADDRESS );

Aqui SOCKET é o descritor retornado pela chamada socket () e ADDRESS é um endereço de socket (para TCP / IP) contendo três elementos -

  • A família de endereços (para TCP / IP, AF_INET, provavelmente 2 em seu sistema).

  • O número da porta (por exemplo, 21).

  • O endereço de Internet do computador (por exemplo, 10.12.12.168).

Como o bind () é usado por um servidor, que não precisa saber seu próprio endereço, a lista de argumentos se parece com isto -

use Socket        # This defines PF_INET and SOCK_STREAM

$port = 12345;    # The unique port used by the sever to listen requests
$server_ip_address = "10.12.12.168";
bind( SOCKET, pack_sockaddr_in($port, inet_aton($server_ip_address)))
   or die "Can't bind to port $port! \n";

o or die cláusula é muito importante porque se um servidor morrer sem conexões pendentes, a porta não será imediatamente reutilizável, a menos que você use a opção SO_REUSEADDR usando setsockopt()função. Aquipack_sockaddr_in() A função está sendo usada para empacotar a porta e o endereço IP em formato binário.

A chamada listen ()

Se este for um programa de servidor, é necessário emitir uma chamada para listen()na porta especificada para escutar, ou seja, aguardar as solicitações de entrada. Esta chamada tem a seguinte sintaxe -

listen( SOCKET, QUEUESIZE );

A chamada acima usa o descritor SOCKET retornado pela chamada socket () e QUEUESIZE é o número máximo de solicitações de conexão pendentes permitidas simultaneamente.

A chamada de aceitar ()

Se este for um programa de servidor, é necessário emitir uma chamada para o access()função para aceitar as conexões de entrada. Esta chamada tem a seguinte sintaxe -

accept( NEW_SOCKET, SOCKET );

O descritor SOCKET de aceitação da chamada recebida retornado pela função socket () e após a conclusão bem-sucedida, um novo descritor de socket NEW_SOCKET é retornado para todas as comunicações futuras entre o cliente e o servidor. Se a chamada access () falhar, ela retornará FLASE, que é definido no módulo Socket que usamos inicialmente.

Geralmente, accept () é usado em um loop infinito. Assim que uma conexão chega, o servidor cria um processo filho para lidar com ela ou o atende sozinho e então volta para ouvir mais conexões.

while(1) {
   accept( NEW_SOCKET, SOCKT );
   .......
}

Agora todas as chamadas relacionadas ao servidor acabaram e vamos ver uma chamada que será solicitada pelo cliente.

Chamadas de soquete do lado do cliente

A chamada connect ()

Se você for preparar um programa cliente, primeiro você usará socket() chamada para criar um soquete e então você teria que usar connect()ligue para se conectar ao servidor. Você já viu a sintaxe da chamada socket () e ela permanecerá semelhante à chamada socket () do servidor, mas aqui está a sintaxe paraconnect() chamar -

connect( SOCKET, ADDRESS );

Aqui SCOKET é o descritor de socket retornado por socket (chamada) emitido pelo cliente e endereço é um endereço de socket semelhante ao ligamento chamada, exceto que ele contém o endereço IP do servidor remoto.

$port = 21;    # For example, the ftp port
$server_ip_address = "10.12.12.168";
connect( SOCKET, pack_sockaddr_in($port, inet_aton($server_ip_address)))
   or die "Can't connect to port $port! \n";

Se você se conectar ao servidor com sucesso, poderá começar a enviar seus comandos para o servidor usando o descritor SOCKET, caso contrário, seu cliente apresentará uma mensagem de erro.

Cliente - Exemplo de servidor

A seguir está um código Perl para implementar um programa cliente-servidor simples usando o socket Perl. Aqui, o servidor escuta as solicitações de entrada e, uma vez que a conexão é estabelecida, ele simplesmente responde Smile do servidor . O cliente lê aquela mensagem e imprime na tela. Vamos ver como isso foi feito, supondo que temos nosso servidor e cliente na mesma máquina.

Script para criar um servidor

#!/usr/bin/perl -w
# Filename : server.pl

use strict;
use Socket;

# use port 7890 as default
my $port = shift || 7890;
my $proto = getprotobyname('tcp');
my $server = "localhost";  # Host IP running the server

# create a socket, make it reusable
socket(SOCKET, PF_INET, SOCK_STREAM, $proto)
   or die "Can't open socket $!\n";
setsockopt(SOCKET, SOL_SOCKET, SO_REUSEADDR, 1)
   or die "Can't set socket option to SO_REUSEADDR $!\n";

# bind to a port, then listen
bind( SOCKET, pack_sockaddr_in($port, inet_aton($server)))
   or die "Can't bind to port $port! \n";

listen(SOCKET, 5) or die "listen: $!";
print "SERVER started on port $port\n";

# accepting a connection
my $client_addr;
while ($client_addr = accept(NEW_SOCKET, SOCKET)) {
   # send them a message, close connection
   my $name = gethostbyaddr($client_addr, AF_INET );
   print NEW_SOCKET "Smile from the server";
   print "Connection recieved from $name\n";
   close NEW_SOCKET;
}

Para executar o servidor em modo de segundo plano, execute o seguinte comando no prompt do Unix -

$perl sever.pl&

Script para criar um cliente

!/usr/bin/perl -w
# Filename : client.pl

use strict;
use Socket;

# initialize host and port
my $host = shift || 'localhost';
my $port = shift || 7890;
my $server = "localhost";  # Host IP running the server

# create the socket, connect to the port
socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2])
   or die "Can't create a socket $!\n";
connect( SOCKET, pack_sockaddr_in($port, inet_aton($server)))
   or die "Can't connect to port $port! \n";

my $line;
while ($line = <SOCKET>) {
   print "$line\n";
}
close SOCKET or die "close: $!";

Agora vamos iniciar nosso cliente no prompt de comando, que irá se conectar ao servidor e ler a mensagem enviada pelo servidor e exibir a mesma na tela da seguinte maneira -

$perl client.pl
Smile from the server

NOTE - Se você estiver fornecendo o endereço IP real em notação de ponto, é recomendável fornecer o endereço IP no mesmo formato no cliente e no servidor para evitar qualquer confusão.