Página 1 de 3 123 ÚltimoÚltimo
Resultados 1 a 10 de 28

Tópico: Tutorial de Sockets para iniciantes - C

  1. #1
    Membro
    Data de Ingresso
    Nov 2005
    Localização
    Minas Gerais :: Belo Horizonte
    Posts
    398
    Post Thanks / Like

    Tutorial de Sockets para iniciantes - C

    Tutorial Bísico de Sockets - Parte 1
    by Dark_Side

    Atendendo aos pedidos de alguns usuírios, estou escrevendo este pequeno tutorial de sockets em C, para Windows.
    Abordarei nesta etapa apenas o uso do protocolo TCP, jí que é o mais comum. No próximo módulo, demonstrarei o uso do UDP, e outras funções legais :).


    Conteúdos que serão abordados:

    1) Introdução.
    2) Preparando e criando Sockets.
    3) Sockets - Criando um programa Servidor.
    4) Sockets - Criando um programa Cliente.
    5) Enviando dados e Recebendo dados.
    6) Finalizando uso do socket.
    7) Código de exemplo - simples chat.
    8) Considerações finais.

    Introdução
    Um dos resursos mais atrativos na programação em C, é o uso de Sockets. O uso de sockets permite o desenvolvimento de vírias aplicações. Exploits, flooders e programas cliente/servidor são poucos exemplos de aplicativos que podemos desenvolver.


    Preparando e criando Sockets.
    Para utilizarmos sockets em C, precisamos incluir todos os headers e bibliotecas necessírios.
    Observe o código:
    Código:
    #include <stdio> 
    #include <winsock> 
    #include <conio>
    WSADATA data; 
    SOCKET winsock; 
    SOCKADDR_IN sock; 
    int main(){ 
    if(WSAStartup(MAKEWORD(1,1),&data)==SOCKET_ERROR){ 
    printf("Erro ao inicializar o winsock"); 
    return 0; 
    } 
    if((winsock = socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR){ 
    printf("Erro ao criar socket"); 
    return 0; 
    } 
    printf("Socket iniciado!");
    getch();
    closesocket(winsock);
    WSACleanup();
    return 0;
    }
    Explicando o código:

    #include <winsock>
    Inclui o header do winsock.

    WSADATA data;
    SOCKET winsock;
    Variíveis que recebem o valor da inicialização e criação do socket.

    SOCKADDR_IN sock;
    Struct -> contém a configuração do socket a ser usado o ip, a porta e a famàlia do socket.


    if(WSAStartup(MAKEWORD(1,1),&data)==SOCKET_ERROR){
    printf("Erro ao inicializar o winsock");
    return 0;
    }

    WSAStartup - Inicializa o uso do winsock.
    A sintaxe é : WSAStartup(VERSAO_DO_WINSOCK,ENDEREÇO DA VARIÁVEL)

    A função retorna o valor 0 (zero) quando é finalizada com sucesso ou -1, quando um erro ocorre.

    if((winsock = socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR){
    printf("Erro ao criar socket");
    return 0;
    }

    socket - Inicializa o socket.
    A sintaxe é: socket(FAMILIA,TIPO_DE_PROTOCOLO,0)

    Para FAMILIA, temos diversos tipos, utilizaremos o AF_INET, para nosso tutorial.

    Tipo de protocolo:

    SOCK_STREAM -> protocolo TCP
    SOCK_DGRAM -> protocolo UDP
    SOCK_RAW -> protocolo para RAW SOCKETS.

    Utilizaremos o SOCK_STREAM.

    Assim como a função WSAStartup, a esta retorna os valores:
    0 (Socket inicializado) ou 1 (não inicializado).

    Sockets - Criando um programa Servidor.
    Observe o código:

    Código:
    #include <stdio> 
    #include <conio>
    #include <winsock> 
    #include <windows> //Repara que utilzaremos este header para utilizarmos a função Sleep(); 
    WSADATA data; 
    SOCKET winsock; 
    SOCKADDR_IN sock; 
    int main(){ 
    if(WSAStartup(MAKEWORD(1,1),&data)==SOCKET_ERROR){ 
    printf("Erro ao inicializar o winsock"); 
    return 0; 
    } 
    if((winsock = socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR){ 
    printf("Erro ao criar socket"); 
    return 0; 
    } 
    sock.sin_family=AF_INET; 
    sock.sin_port=htons(1234); 
    if(bind(winsock,(SOCKADDR*)&sock,sizeof(sock))==SOCKET_ERROR){ 
    printf("Erro colocar utilizar a funcao BIND"); 
    return 0; 
    } 
    listen(winsock,1); 
    while((winsock = accept(winsock,0,0))==SOCKET_ERROR) 
    { 
    Sleep(1); 
    } 
    printf("Cliente conectado!"); 
    getch();
    closesocket(winsock);
    WSACleanup();
    return 0; 
    }
    O que vemos de novidade no código?
    Código:
    if(bind(winsock,(SOCKADDR*)&sock,sizeof(sock))==SOCKET_ERROR){ 
    printf("Erro colocar utilizar a funcao BIND"); 
    return 0; 
    } 
    listen(winsock,1); 
    while((winsock = accept(winsock,0,0))==SOCKET_ERROR) 
    { 
    Sleep(1); 
    } 
    printf("Cliente conectado!"); 
    getch();
    closesocket(winsock);
    WSACleanup();
    return 0; 
    }
    Assim como a função WSAStartup e socket, a função BIND também retorna um valor, que por sinal, são os mesmos.Esta função é responsível por colocar o socket no modo BIND(configurí-lo na porta local).

    listen(winsock,1) -> Coloca o socket em modo de espera, aceitando 1 conexão.
    Código:
    while((winsock = accept(winsock,0,0))==SOCKET_ERROR) 
    { 
    Sleep(1); 
    } 
    printf("Cliente conectado!"); 
    getch();
    closesocket(winsock);
    WSACleanup();
    return 0; 
    }
    Criamos um loop para verificarmos se houve um pedido de conexão, como a função ACCEPT retorna -1 quando não hí pedidos, o loop serí feito até que o retorno seja diferente de -1, que indica um pedido de conexão.
    Ao sair do loop, é mostrada na tela uma mensagem dizendo que houve uma conexão e em seguida o programa encerra.


    Sockets - Criando um programa Cliente.
    Observe o código:
    Código:
    #include <stdio>
    #include <winsock>
    #include <conio>
    WSADATA data;
    SOCKET winsock;
    SOCKADDR_IN sock;
    int main(){
    if(WSAStartup(MAKEWORD(1,1),&data)==SOCKET_ERROR){
    printf("Erro ao inicializar o winsock");
    return 0;
    }
    if((winsock = socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR){
    printf("Erro ao criar socket");
    return 0;
    }
    sock.sin_family=AF_INET;
    sock.sin_port=htons(1234);
    sock.sin_addr.s_addr=inet_addr("127.0.0.1");
    if(connect(winsock,(SOCKADDR*)&sock,sizeof(sock))==SOCKET_ERROR){
    printf("Erro ao se conectar");
    return 0;
    }
    printf("Conectado!");
    getch();
    closesocket(winsock);
    WSACleanup();
    return 0;
    }
    Analisando:
    Código:
    sock.sin_addr.s_addr=inet_addr("127.0.0.1") => Indica o IP o qual queremos conectar.
    connect(winsock,(SOCKADDR*)&sock,sizeof(sock)) => Conecta o socket.
    Como não poderia ser diferente, temos os valores 0(sucesso) ou -1(falha) como retorno da função connect().
    Esta função é uma das mais utilizadas na programação em SOCKET's. :)

    Enviando dados e Recebendo dados.
    Chegamos à melhor parte....
    O envio e recebimento de dados.
    Temos duas funções que se encarregam disso: send e recv.

    Lembrando que estaremos aptos a utilizí-las, apenas após uma conexão estiver sido estabelecida.

    Enviando dados:
    Código:
    #include <string>
    char buffer[1024];
    send(winsock,buffer,strlen(buffer),0)
    Analisando a funcão temos:
    send(SOCKET,BUFFER,TAMANHO,0);

    SOCKET -> nosso socket que foi criado;
    BUFFER -> dados a enviar;
    TAMANHO -> tamanho dos dados;

    Recebendo dados:

    Código:
    #include <string>
    char buffer[1024];
    int byes;
    while(1){
    memset(buffer,0,1024);
    bytes = recv(winsock,buffer,strlen(buffer),0)
    if(bytes==-1)
    return 0;
    }
    Analisando a funcão temos:
    memset(buffer,0,1024)
    Determinamos um espaço para receber os dados.
    recv(SOCKET,BUFFER,TAMANHO,0);

    SOCKET -> nosso socket que foi criado;
    BUFFER -> variível que armazenarí os dados;
    TAMANHO -> tamanho da variível;

    Note que se o número de bytes for igual a 0, o programa termina.

    Finalizando o uso do socket.
    Quando queremos fechar um socket, utilizamos:
    closesocket(NOME_DO_SOCKET);
    No nosso exemplo:
    closesocket(winsock);
    Fechamos o nosso socket, mas ainda não finalizamos o uso do winsock, isto é, enquanto o programa estiver rodando, estaremos aptos a criar novos sockets. Ao finalizar um programa que utiliza sockets, utilizamos sempre WSACleanup() para encerrar o uso do winsock.

    Esquema:
    Código:
    HEADERS
    [...]
    int main(){
    [...]
    desenvolvimento do programa
    [...]
    closesocket(winsock);
    WSACleanup()
    return 0;
    }
    Código de exemplo - simples chat
    CLIENTE.C
    Código:
    #include <stdio>
    #include <winsock>
    #include <conio>
    #include <windows>
    #include <string>
    WSADATA data;
    SOCKET winsock;
    SOCKADDR_IN sock;
    char buffer[1024];
    char buffer2[1024];
    int bytes;
    int main(){
    if(WSAStartup(MAKEWORD(1,1),&data)==SOCKET_ERROR){
    printf("Erro ao inicializar o winsock");
    return 0;
    }
    if((winsock = socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR){
    printf("Erro ao criar socket");
    return 0;
    }
    sock.sin_family=AF_INET;
    sock.sin_port=htons(1234);
    sock.sin_addr.s_addr=inet_addr("127.0.0.1");
    if(connect(winsock,(SOCKADDR*)&sock,sizeof(sock))==SOCKET_ERROR){
    printf("Erro ao se conectar");
    return 0;
    }
    printf("Conectado!\n");
    while(1)
    {
    Sleep(1);
    printf("Digite uma mensagem:\n");
    gets(buffer);
    strcat(buffer,"\r\n");
    send(winsock,buffer,strlen(buffer),0);
    memset(buffer2,0,1024);
    bytes=recv(winsock,buffer2,1024,0);
    if(bytes==-1){
    	printf("Conexão perdida");
    	getch();
    return 0;
    }
    printf(buffer2);
    
    }
    getch();
    closesocket(winsock);
    WSACleanup();
    return 0;
    }
    SERVIDOR.C
    Código:
    #include <stdio> 
    #include <conio> 
    #include <winsock> 
    #include <windows> //Repara que utilzaremos este header para utilizarmos a função Sleep(); 
    WSADATA data; 
    SOCKET winsock; 
    SOCKADDR_IN sock; 
    char buffer[1024];
    char buffer2[1024];
    int bytes;
    int main(){ 
    if(WSAStartup(MAKEWORD(1,1),&data)==SOCKET_ERROR){ 
    printf("Erro ao inicializar o winsock"); 
    return 0; 
    } 
    if((winsock = socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR){ 
    printf("Erro ao criar socket"); 
    return 0; 
    } 
    sock.sin_family=AF_INET; 
    sock.sin_port=htons(1234); 
    if(bind(winsock,(SOCKADDR*)&sock,sizeof(sock))==SOCKET_ERROR){ 
    printf("Erro colocar utilizar a funcao BIND"); 
    return 0; 
    } 
    listen(winsock,1); 
    while((winsock = accept(winsock,0,0))==SOCKET_ERROR) 
    { 
    Sleep(1); 
    } 
    printf("Cliente conectado!"); 
    while(1)
    {
    Sleep(1);
    memset(buffer2,0,1024);
    bytes=recv(winsock,buffer2,1024,0);
    if(bytes==-1){
    	printf("Conexão perdida");
    	getch();
    return 0;
    }
    printf(buffer2);
    printf("Digite uma mensagem:\n");
    gets(buffer);
    strcat(buffer,"\r\n");
    send(winsock,buffer,strlen(buffer),0);
    
    }
    getch();
    closesocket(winsock);
    WSACleanup();
    return 0;
    }
    Considerações finais

    Bem, chegamos ao fim da primeira parte de um simples tutorial de sockets, gostaria que ficasse bem claro que o material apresentado aqui é bem bísico, dedicado aos iniciantes. Aguardem ao próximo tópico, onde mostrarei como utilizar funções interessantes como por exemplo: gethostbyname() - que resolve o nome do host e seu IP, inet_ntoa() - obtém o IP de um host, dentre outras.

    Obs:: O tutorial acima, utiliza o socket no modo blocking, isto é, enquanto uma ação não é executada, as demais não serão também ao decorrer do tempo.
    Mostrarei também como utilizar sockets no modo non-blocking, e se possàvel abordarei sockets em programação WIN32, onde os função são monitoras via LOOP de MSGS (socket assincrono).
    Bye.

  2. #2
    Wannabe
    Data de Ingresso
    Feb 2006
    Posts
    755
    Post Thanks / Like
    Muito legal!!!!

    Ainda não li, mas pareçe estar muito bom!!! QUando eu tiver tempo eu leio!!!

  3. #3
    Newbie
    Data de Ingresso
    Jun 2005
    Posts
    28
    Post Thanks / Like
    muito bom velho..
    que livro tu indica para c/c++
    que tenha sockts. gui, bem... um livro completo?
    abçs vlw

  4. #4
    Newbie
    Data de Ingresso
    May 2006
    Posts
    123
    Post Thanks / Like

    problema..

    essa não é a primeira vez que tento me aventurar no c/c++ e ocorre o problema de eu nao ter os .h necessarios, uso o dev-c++ e fui compilar seu codigo e deu erro, primeiro dizendo que as includes não existiam. depois, colocando .h no final delas ocorre um erro assim:

    [Link error] undefinied reference to '-------'

    entre os ------ apareceu:

    WSAStartup@8
    socket@12
    ....

    o que poderia ser?

    grato.

  5. #5
    Guest
    Veio brigadão aew inclusive eu tinha le passado um mp para pedir algo sobre isso.
    Vow ler.
    Vlw mesmo.

  6. #6
    Guest
    Veio vc não sabe onde consigo atividades sobre socket não de preferencia usando somente o conhecimento adiquirido nessa breve tutorial que você fez?

  7. #7
    Membro
    Data de Ingresso
    Nov 2005
    Localização
    Minas Gerais :: Belo Horizonte
    Posts
    398
    Post Thanks / Like

    Re: problema..

    Citação Postado originalmente por kayo
    essa não é a primeira vez que tento me aventurar no c/c++ e ocorre o problema de eu nao ter os .h necessarios, uso o dev-c++ e fui compilar seu codigo e deu erro, primeiro dizendo que as includes não existiam. depois, colocando .h no final delas ocorre um erro assim:

    [Link error] undefinied reference to '-------'

    entre os ------ apareceu:

    WSAStartup@8
    socket@12
    ....

    o que poderia ser?

    grato.
    Hi,
    você deve incluir a Lib do winsock "wsock32.lib". Utilizando o DEV C++, o processo pode ser feito da seguinte maneira:

    1) Ferramentas->Opções do compilador
    2) Adicione a seguinte linha nas opções do LINKER: -l wsock32
    3) Compile o código novamente.
    Bye.

  8. #8
    Newbie
    Data de Ingresso
    May 2006
    Posts
    123
    Post Thanks / Like
    gracias hermano vo la no win pra testar.

  9. #9
    Membro
    Data de Ingresso
    Nov 2005
    Localização
    Minas Gerais :: Belo Horizonte
    Posts
    398
    Post Thanks / Like
    Citação Postado originalmente por Calkines
    muito bom velho..
    que livro tu indica para c/c++
    que tenha sockts. gui, bem... um livro completo?
    abçs vlw
    Hi, livros sobre programação em C/C++, eu não conheço. Mas existem ótimas matérias e tutorias espalhados pela internet.
    Bye.

  10. #10
    Membro
    Data de Ingresso
    Nov 2005
    Localização
    Minas Gerais :: Belo Horizonte
    Posts
    398
    Post Thanks / Like
    Citação Postado originalmente por hellb0y
    Veio vc não sabe onde consigo atividades sobre socket não de preferencia usando somente o conhecimento adiquirido nessa breve tutorial que você fez?
    Você pode tentar obter algo em:
    http://olinux.uol.com.br/secoes/section.phl?id_dir=5
    Bye.

Tópicos Similares

  1. Tutorial para iniciantes em C
    Por Dalt0n no fórum C,C++
    Respostas: 40
    Último Post: 31 Dec 2011, 23:49

Permissões de Postagem

  • Você não pode iniciar novos tópicos
  • Você não pode enviar respostas
  • Você não pode enviar anexos
  • Você não pode editar suas mensagens
  •