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: 109.435 ]

Por: C00L3R_ em 06/07/2010 | Blog: http://bugsec.com.br


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: tony.unix@yahoo.com.br or c00f3r@gmail.com
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 OpenBSD como desktop

Usando o PF - Packet Filter

Usando o NetBSD como desktop

Bind: Explorando e evitando falhas

Trabalhando com arquivos no Perl

Leitura recomendada

Controlando UPLOAD com o CBQ

Monitorando o consumo de banda com Bwbar

O Modelo de Referência OSI

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

O ? Alternativo em C/C++

  
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
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts