+ Responder ao Tópico



  1. #1

    Padrão Ajuda com Cliente/Servidor UDP

    Olá pessoal, prazer, me chamo Marina (primeiro tópico hauhauahu), enfim, estou com um trabalho da faculdade que preciso entregar onde o professor pediu que fizessemos um cliente/servidor em UDP. O cliente entra com um código, precisa abrir um arquivo .dat para pegar os ip's e portas de servidores listados para tentar a conexão, e enviar esses dados ao servidor, que vai recebe-lo e reenviar para os outros servidores a mesma mensagem, fiz os códigos abaixo depois de muita pesquisa na net:

    clientudp.c
    Código :
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <string.h>
    #include <unistd.h>
    #include <arpa/inet.h>
     
    main(int argc, char ** argv)
    {
     
        struct sockaddr_in scheduller;
          int s, sched_address_size;
           char buf;
        char ip[16];
        int port[6];
     
       if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
       {
           perror("socket()");
           exit(1);
       }
     
        printf("\n\nMenu\n");
        printf("-----------------------------------------\n");
        printf("Para incluir digite (I): ");
        printf("\nPara alterar digite (A): ");
        printf("\nPara excluir digite (E): ");
        printf("\nPara consultar digite (C): ");
        printf("\n");
        gets(buf);
     
     
        FILE * fp;
     
        if (fp=fopen("config.dat","r") != NULL)
        {
     
        while(fscanf(fp, "%s %i", ip, port) != NULL)
        {
            scheduller.sin_family = AF_INET;
            scheduller.sin_addr.s_addr = inet_addr(ip);
            scheduller.sin_port = htons(port);
     
                if (sendto(s, buf, (strlen(buf)+1), 0, (struct sockaddr *)&scheduller, sizeof(scheduller)) < 0)
            {
                perror("A mensagem não pode ser enviada");
                exit(2);
            }
            else
            {
                sendto(s, buf, (strlen(buf)+1), 0, (struct sockaddr *)&scheduller, sizeof(scheduller));
                break;
            }
     
           }
        sched_address_size = sizeof(scheduller);
        if(recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *) &scheduller, &sched_address_size) <0)
        {
            perror("Erro ao receber a resposta");
            exit(4);
        }
        printf("%s\n", buf);
        fflush(stdout);    
        }
        else
            printf("Nao foi possivel se conectar ao servidor, tente mais tarde");
        fclose(fp);    
        close(s);
    }
    Na hora que entro com o código, dá erro de Segmentação, não faço ideia do que possa ser. O arquivo abaixo são os endereços que ele precisa testar na hora da conexão, mas não sei se está abrindo ou não o arquivo pois o erro ocorre antes.

    config.dat
    Código :
    127.0.0.1 7001
    127.0.0.1 7002
    127.0.0.1 7003
    Vou postar o código do servidor também apesar dele ainda só estar recebendo a mensagem e mandando a resposta, sem reenviar para os demais servidores.

    servidorudp.c
    Código :
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <string.h>
    #include <unistd.h>
    #include <arpa/inet.h>
     
    main(int argc, char ** argv)
    {
       int sockint,s; 
       socklen_t namelen;
       socklen_t client_address_size;
       struct sockaddr_in client, scheduller;
       char buf;
     
       if (argc < 2) {
          perror("Quantidade de parametros incorreta!");
          printf("\n%s [port]\n",argv[0]); 
          exit(1);
       }
     
     
       if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
       {
           perror("socket()");
           exit(1);
       }
     
       scheduller.sin_family      = AF_INET;
       scheduller.sin_port        = htons(atoi(argv[1]));
       scheduller.sin_addr.s_addr = INADDR_ANY;
     
     
       if (bind(s, (struct sockaddr *)&scheduller, sizeof(scheduller)) < 0)
       {
           perror("bind()");
           exit(2);
       }
     
       namelen = sizeof(scheduller);
       if (getsockname(s, (struct sockaddr *) &scheduller, &namelen) < 0)
       {
           perror("getsockname()");
           exit(3);
       }
        fflush(stdout);
     
       client_address_size = sizeof(client);
       if(recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *) &client,
                &client_address_size) <0)
        {
        perror("recvfrom()");
        exit(4);
        }
        fflush(stdout);
     
        printf("Protocolo: %s\n", buf);
     
        strcpy(buf, "Mensagem recebida");
     
        if(sendto(s, buf, (strlen(buf)+1), 0, (struct sockaddr *) &client,sizeof(client)) <0)
        {
         perror("recvfrom()");
         exit(4);
        }
     
        close(s);
    }
    Bom é isso, se alguém puder me explicar onde estou errando (acho que estou errando em tudo, mas beleza), eu agradeceria muito.

    Até!

  2. #2

    Padrão

    Cara, a primeira falha de segmentação, acredito eu, é causada por fscanf nunca retornar NULL. Se você der uma olhada no cabeçalho do fscanf, verá que ele retorna um inteiro. E NULL é um ponteiro, o ponteiro inválido.

    Portanto, dá uma corrigida nisso. Provavelmente, o que você queria fazer era verificar se fscanf havia chegado ao fim do arquivo. Se sim, o correto seria verificar o EOF. Tipo "whiel (fscanf(...) != EOF) {".

    Espero ter ajudado.

    ps: tente aprender a usar o gdb (GNU Debugger). E, pelo menos aqui no gcc, o compilador gera uma mensagem de erro quando tenta-se fazer comparações em tipo incompactíveis. Dá uma olhada no opção -Wall do gcc.

    Boa sorte!

  3. #3

    Padrão

    Valeu, esse NULL eu tinha colocado porque um amigo meu disse que poderia ser isso o problema, já que eu estava usando o feof para comparar, mas mesmo mudando continuou o erro, no fim eu fiz usando o fgets para ler o arquivo .dat, deu um baita trabalho mas saiu. Fazendo o debug do programa descobri que ao abrir o arquivo ele só estava lendo a primeira coluna, que contem o ip e pulava para a próxima linha, não pegando o número da porta, mas pelo que andei pesquisando no google a maneira como eu coloquei era para pegar as duas partes com o fscanf, mas ele não pega. Vou levar o codigo abaixo para a aula e ver com o professor se ele sabe o porque disso.

    Valeu de novo, abraços.