BSD Sockets em linguagem C

Venho neste artigo explicar como funciona sockets em ANSi C, explicar portabilidade e exemplos reais e diferentes de artigos semelhantes. Enfim, aqui você aprenderá a usar sockets na prática.

[ Hits: 114.096 ]

Por: C00L3R_ em 06/07/2010 | Blog: https://github.com/CoolerVoid


Funções read(), send() e exemplo cliente HTTP



Vamos usar algumas bibliotecas, são elas "sys/types.h","sys/sockets.h","netinet/in.h", "errno.h" e "netdb.h".

Outra função que vamos usar é a connect(). Seria uma função responsável pela conexão de seu socket cliente com um serviço servidor qualquer.

As headers necessárias para o uso dessa função são "sys/types.h" e "sys/socket.h".

Uma vez declaradas as headers, vamos declarar a função propriamente dita:

int connect(Meusocket,(struct sockaddr * )&server, sizeof(server));

read() - usada para ler mensagens enviadas de um socket. Sua sintaxe é igual a da função write():

int read (socket, *buffer, tamanho utilizado do buffer);

send() - usada para enviar uma mensagem para um socket.

int Send (socket, *mensagem, tamanho da mensagem, parametros adicionais)

Parâmetros adicionais podem ser:

#define MSG_OOB           0x1     /* process out-of-band data*/
#define MSG_DONTROUTE     0x4     /* bypass routing, usedirect interface */
#define MSG_DONTWAIT      0x40    /* don't block */
#define MSG_NOSIGNAL      0x2000  /* don't raise SIGPIPE */

  • MSG_OOB - envia mensagens Out-Of-banda (OOB) - fora de banda - para sockets que suportam esse tipo de mensagem. Esse tipo de parâmetro é o calcanhar de aquiles do Windows 95, que trava com uma mensagem OOB (famoso winnuke).
  • MSG_DONTROUTE - usado como debugador, para encontrar problemas.
  • MSG_DONTWAIT - permite operações "non-blocking".
  • MSG_NOSIGNAL - Ao mandar SIGPIPE em erros em sockets stream quando o outro endereço quebra a conexão.

Exemplo de utilização:

char cso [] = "sai fora cara"

send (newSock, cso, sizeof (cso), 0); //Sem parâmetros adicionais

Continuando...

Vou mostrar um exemplo de sockets usando protocolo HTTP com funções socket, connect, read e send. Vamos criar um simples cliente que lê uma source de uma página http, veja que antes de mandar para socket tenho que converter o HOST em IP.

/*

GarageCode coolest things Hehehe
http://GarageCode.tk

*Function this programm
This is Simples programm to splain the socket job in
http protocol,to send data and take request from WebServer

(C code with socket)
         ||
         ||
        \  /
         \/
   [GET /index.html HTTP/1.1\nHost: www.site.com\t \n\n]
         ||
         ||
        \  /
         \/
(Apache listening server) if http read return the request with html to socket

this coolest to study sockets and http requests,in the future i make robot
about logic this code...


*tested with GCC 
 i wheel on Unix/Linux/BSD this:
    gcc -o program program.c; ./program

Author: "Cooler_"  
contact: [email protected] or [email protected]
license: GPL2

visit this site: http://BotecoUnix.com.br
Real Geeks BotecoUnix

greetz 
Thanks _mlk_ , m0nad,IAK,Fox,edenc,D3lf0,zepplin and f0kerdebug.

       __ ____
      /  /.  .\
      |--| 0 0 |
      |  | . . |
       \ \____/
   _----\___/---- _
 /___\          /___\   
 |   |  |_|0|_| |   |
 |   |  |_|_|0| |   |    rick taylor from
 |   |  |0|0|0| |   |   The Game SplatterHouse 2 at 1992
 |   |          |  /  
  \  ) -------- ( /
  /\/     |)    \/\
  |/             \ |
  (       |        )
  |\      |       /|
  |       |        |
   \      |       /
    \ ___ |  ___ /
     =o=  |  =o=
    /xx   |  xx\      Code and art by Cooler_ 
 (_______| |______) 
  
      
*/
//libs diversas para tratar entrada, saida, memoria, string, erros...
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "errno.h"
#include "unistd.h"
//lib padrão para uso da socket
#include "netinet/in.h"
#include "arpa/inet.h"
#include "sys/types.h"
#include "sys/socket.h"
// lib para usar para converter host para ip
#include "netdb.h"

#define MAXSIZE 800
#define MAX 500
int main() {
  int sockfd,n;
  char *url,buff[MAXSIZE],sBuff[MAXSIZE],host[MAX],page[MAX],enter[MAX];
/*
no protocolo http o cliente manda dados com a info

GET /index.html HTTP/1.1
Host: www.site.com

para tal feito ficaria em C
GET /index.html HTTP/1.1\nHost: www.site.com\t \n\n

Peguei entrada um link http extraimos host e dados do GET
com sscanf,também pode ser feito com split ou regex,bom estraido
dados usei strcat para concatenar as variaveis alfanumericas
*/

  char getpage[MAX]="GET /";
// struct do netdb para converter host para ip
  struct hostent *ip;
// struct da socket
  struct sockaddr_in end;

//pegamos entrada do usuario
  printf("digite um link: ");
   fgets(enter, sizeof(enter), stdin);
   enter[strlen(enter)-1] = '\0';
//extraimos host e local da pagina
  sscanf(enter, "http://%99[^/]/%99[^\n]", host, page);
   printf("DNS = \"%s\"\n", host);
   printf("Page = \"%s\"\n\n", page);
   strcat(page," HTTP/1.1\nHost: ");
   strcat(page,host);
   strcat(page,"\t \n\n");

// função da lib netdb.h para converter ai nosso host para IP
  ip = gethostbyname(host);
  url=inet_ntoa(*(struct in_addr *)ip->h_addr);
  strcat(getpage,page);
  printf("%s",getpage);

/*
separamos buff para pegar resposta do server
mas antes preenchemos a memoria com \0
usamos sbuff para armazenar dados do envio
*/

  memset(buff,'\0',sizeof(char)*MAXSIZE);
  memset(sBuff,'\0',sizeof(char)*MAXSIZE);
  strcpy(sBuff,getpage);

// condições simples em caso de erro
  if( (sockfd=socket(AF_INET,SOCK_STREAM,0)) < 0 ){
    perror("socket");
    return errno;
  }

// definimos a porta usado no caso 80
/*
sin familia
+ AF_INET      (ARPA INTERNET PROTOCOLS) - "A mais usada"
+ AF_UNIX      (UNIX INTERNET PROTOCOLS)
+ AF_ISO       (ISO PROTOCOLS)
+ AF_NS        (XEROX NETWORK SYSTEM PROTOCOLS)
*/

  end.sin_family=AF_INET;
  end.sin_port=htons(80);/* Aqui é o seguinte:
                                 htons significa "host to network short", como
                                 é short trabalha com 2 bytes,mas ha ainda
                                 outros tipos como: htonl("host to network
                                 long",4 bytes), ntós("network to host
                                 short",2 bytes), ntól("network to host
                                 long", 4 bytes). */


  if( inet_pton(AF_INET,url,&end.sin_addr) < 0){
    perror("inet_pton");
    return errno;
  }

  memset(end.sin_zero,'\0',8);

  if(connect(sockfd,(struct sockaddr*)&end,sizeof(struct sockaddr)) < 0){
    perror("connect");
    return errno;
  }

  if( (send(sockfd, sBuff, strlen(sBuff), 0)) < 0){
    perror("send");
    close(sockfd);
    return errno;
  }
// recebe a resposta e mostra saida
  while((n=read(sockfd,buff,MAXSIZE)) > 0) fprintf(stdout,"%s",buff);

  close(sockfd);
  return 0;
}

Compile:

gcc -o client client.c; ./client

Vai pedir um link, digite por exemplo http://www.botecounix.com.br/blog e veja que bacana.

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. Explanação ao TCP/IP
   3. O que é socket
   4. Funções read(), send() e exemplo cliente HTTP
   5. Funções listen(), bind(), accept() e exemplo de servidor HTTP
   6. Na prática fazendo um FUZZER TCP
   7. Servidor e cliente com fork
   8. Servidor de comandos e scanner de portas
   9. Simple socket library
   10. Explanação ao UDP e exemplo de servidor e cliente
   11. Exemplo UDP Flood
   12. Portabilidade
   13. Conclusão
Outros artigos deste autor

Usando o NetBSD como desktop

Trabalhando com arquivos no Perl

Usando OpenBSD como desktop

Usando o PF - Packet Filter

Ponteiros - Saindo de Pesadelos

Leitura recomendada

Controlando UPLOAD com o CBQ

O Modelo de Referência OSI

Monitorando o consumo de banda com Bwbar

Tutorial - Aplicação em C para transferência de arquivo usando socket TCP e Thread

Ponteiros void na linguagem C (parte 2)

  
Comentários
[1] Comentário enviado por VonNaturAustreVe em 06/07/2010 - 03:24h

Excelente cara vou ler tudo :)

[2] Comentário enviado por removido em 06/07/2010 - 05:29h

Hey C00L3R,
Parabéns, é um ótimo artigo. Minhas dúvidas surgiram após meus testes.
Um abraço.

[3] Comentário enviado por andrezc em 06/07/2010 - 08:12h

Cara, realmente esse é um dos melhores artigos que eu já li por aqui. Parabéns.

[4] Comentário enviado por werneral em 06/07/2010 - 11:18h

Muito bom! Obrigado!

[5] Comentário enviado por uberalles em 06/07/2010 - 11:43h

verdadeira aula, velho. parabéns!
muito bom "resumão" do Unix Network programming. Nunca consegui fazer nada decente em sockets e esta tua aula deverá me ajudar muito.

[6] Comentário enviado por stremer em 07/07/2010 - 15:28h

para quem interessar, ha algum tempo atras escrevi um script mostrando como criar um robo http e enviei ao VOL.

http://www.vivaolinux.com.br/script/Robo-HTTP-usando-socket-e-codigo-multiplataforma

Interessante para quem esta aprendendo sockets...

OTIMO ARTIGO

[7] Comentário enviado por andrezc em 07/07/2010 - 15:43h

Opa stremer, eu cheguei a ver este seu script, realmente fabuloso.

Um abraço.

[8] Comentário enviado por fernandopinheiro em 07/07/2010 - 20:23h

Parabens, muito bom!!

[9] Comentário enviado por brunosolar em 08/07/2010 - 09:48h

Parabens realmente muito bom. So queria fazer um comentario sobra a parte do UDP flood. Sim hoje em dia qualquer firewal simples pode recusar este tipo de pacote.

No entanto dependendo da quantidade de pacotes UDP enviados (leia-se DDOS) você poderá ser "derrubado" pois o firewall irá gastar muito processador para descatar todos os pacotes. A melhor solução (AINDA) para ataques DOS / DDOS é diretamente no ISP onde eles irão setar no roteador o IP do atacante para /dev/null (exemplo). claro que voce corre o risco de perder algum cliente que faça parte da rede redirecionada.

No mais excelente trabalho.

[10] Comentário enviado por shazaum em 24/09/2010 - 11:44h

opa, no fuzzer faltou uma lib...

#include <netinet/in.h>

[11] Comentário enviado por thomasawrd em 18/07/2014 - 12:41h

parabéns cara excelente artigo,me ajudou muito.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts