Exemplo simples de criação de Sockets

Uma socket é uma extremidade de um canal de transmissão entre dois processos através de uma rede de computadores.

Representa a ligação com outro ponto da rede e através da mesma pode-se realizar transferência de dados.

Exemplo do uso de sockets:

  • Firefox a transferir uma página de um servidor;
  • Ligação SSH de uma máquina para outra;
  • Ligação FTP para gerir ficheiros.

As sockets funcionam como caixas (“tomadas”), que ligam um determinado programa a outro programa;

Em sockets TCP existe um cliente e um servidor.

Uma comunicação pode ser feita de forma síncrona ou assíncrona

A forma síncrona resulta no bloqueio do programa enquanto espera pela recepção ou pelo envio de dados.

A forma assíncrona devolve os dados disponíveis no momento em que a função de recepção de dados é chamada e sai imediatamente se não houver ainda dados disponíveis.

Tipos

  • UDP - Datagramas
  • TCP – Stream Oriented
  • Unix - Comunicação Local entre processos
  • SCTP – Stream Control Transmission Protocol
  • RAW – sem protocolo definido (só leva cabeçalho IP)
  • Entre outros…

Tipo UDP

  • Sem garantia de entrega;
  • Sem garantia de ordem;
  • Sem estabelecimento de ligação;
  • Garantia da consistência do pacote;
  • O pacote tem limites definidos quanto à mensagem;
  • Não sofre fragmentação ao chegar ao destino.

Tipo TCP

  • Fluxo continuo de dados, bidireccional, com garantia de entrega;
  • Dados chegam sempre na mesma ordem em que foram enviados e chegam sempre correctamente;
  • Se não chegarem correctamente os dados são reenviados;
  • Os dados podem ser fragmentados.

Cliente-Servidor

É o cliente que faz os pedidos de ligação;

O servidor está sempre à escuta e decide se e quando aceita um pedido de ligação de um cliente.

Um cliente normalmente comunica com um servidor de cada vez, por outro lado, um servidor pode receber ligações de vários clientes.

Código Cliente

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstdio>
#include <cstring>


int main (int p_argc, char** p_argv)
{

  //PT: criação da socket
  int link = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   //PT: criação do endereço
  struct sockaddr_in address;

  //PT: preenchimento do endereço
  //PT: indicar a utilização do IPv4
  address.sin_family = AF_INET;
  
  //PT: host to network short (coloca a porta na ordem de rede). Porta do servidor a ser ligada.
  address.sin_port = htons(1100);
  
  //PT: host to network long (coloca o endereço na ordem de rede). 127<<24 | 1 = 127.0.0.1!!
  address.sin_addr.s_addr = htonl(127<<24 | 1);

  //PT: estabelecer ligação ao servidor
  connect(link, (struct sockaddr *) &address, sizeof(address));

  for(int i = 1; i < p_argc; ++i)
  {
    send(link, p_argv[i], strlen(p_argv[i]), 0);
    send(link, " ", 1, 0);
  }
  
}

Código Servidor

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstdio>


int main(int p_argc, char** p_argv)
{
  //PT: criação da socket  
  int escuta = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  //PT: criação do endereço
  struct sockaddr_in address;

  //PT: preenchimento do endereço
  //PT: indicar a utilização do IPv4
  address.sin_family = AF_INET;
  
  //PT: Host to network short (coloca a porta na ordem de rede).
  //PT: Escutar na porta 1100.
  address.sin_port = htons(1100);
  
  //PT: Host to network long (coloca o endereço na ordem de rede).
  //PT: Qualquer IP da máquina.
  address.sin_addr.s_addr = htonl(INADDR_ANY);

  //PT: Ligação da porta, ao endereço e à socket criada.
  bind(escuta, (const struct sockaddr *) &address, sizeof(address));

  //PT: Colocar a socket à escuta
  listen(escuta, 1);

  //PT: Estruturas para receber a info do cliente.
  struct sockaddr_in addclient;
  socklen_t addclientlen = 0;

  //PT: Colocar a aceitar sockets
  int sockclient = 0;
  sockclient = accept(escuta, (struct sockaddr *) &addclient, &addclientlen);

  //PT: Mensagem de sucesso na recepção de uma ligação
  if(0 < sockclient)
    printf("Ligação bem estabelecida.\n");

  char * buffer = new char[1500];
  int numreceived = 0;
  int totalreceived = 0;

  while(1)
  {
    numreceived = recv(sockclient, &buffer[totalreceived], (1499 - totalreceived), 0);
    if(0 >= numreceived)
      break;
    totalreceived += numreceived;
  }
  buffer[totalreceived] = 0;

  printf("%s\n", buffer);
  delete [] buffer;   
}