2015-11-16 4 views
0

Я пытался изменить http://beej.us/guide/bgnet/ «selectserver.c» и позволяют определить пользовательский номер порта и использовать его вместоUserDefined Номер порта

#define PORT "9034" // port we're listening on 

я пытаюсь сделать эту работу ...

int PORT; 
if (argc == 1) { 
    printf("\nNo argument passed. See example: ./selectserver 1234 \n\n"); 
    exit(-1); 
} else { 
    PORT = atoi(argv[1]); 
    printf("PORT NO. : %d \n", PORT); 
} 

char* ptrPORT = (char *)&PORT; 

...

вот код я модифицировал:

/* 
** selectserver.c -- a cheezy multiperson chat server 
*/ 

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 

//#define PORT "10000" // port we're listening on 

// get sockaddr, IPv4 or IPv6: 
void *get_in_addr(struct sockaddr *sa) 
{ 
    if (sa->sa_family == AF_INET) { 
     return &(((struct sockaddr_in*)sa)->sin_addr); 
    } 

    return &(((struct sockaddr_in6*)sa)->sin6_addr); 
} 

int main(int argc, char *argv[]) { 
    int PORT; 
    fd_set master; // master file descriptor list 
    fd_set read_fds; // temp file descriptor list for select() 
    int fdmax; // maximum file descriptor number 
    int listener;  // listening socket descriptor 
    int newfd;  // newly accept()ed socket descriptor 
    struct sockaddr_storage remoteaddr; // client address 
    socklen_t addrlen; 
    char buf[256]; // buffer for client data 
    int nbytes; 

    char remoteIP[INET6_ADDRSTRLEN]; 

    int yes=1;  // for setsockopt() SO_REUSEADDR, below 
    int i, j, rv; 

    struct addrinfo hints, *ai, *p; 

    FD_ZERO(&master); // clear the master and temp sets 
    FD_ZERO(&read_fds); 

    // get us a socket and bind it 
    memset(&hints, 0, sizeof hints); 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_flags = AI_PASSIVE; 

    if (argc == 1) { 
     printf("\nNo argument passed. See example: ./selectserver 1234 \n\n"); 
     exit(-1); 
    } else { 
     PORT = atoi(argv[1]); 
     printf("PORT NO. : %d \n", PORT); 
    } 

    char* ptrPORT = (char *)&PORT; 

    if ((rv = getaddrinfo(NULL, ptrPORT, &hints, &ai)) != 0) { 
      fprintf(stderr, "selectserver: %s\n", gai_strerror(rv)); 
      exit(1); 
    } 

    for(p = ai; p != NULL; p = p->ai_next) { 
     listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol); 
     if (listener < 0) { 
      continue; 
     } 

     // lose the pesky "address already in use" error message 
     setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); 

     if (bind(listener, p->ai_addr, p->ai_addrlen) < 0) { 
       close(listener); 
      continue; 
     } 

     break; 
    } 

    // if we got here, it means we didn't get bound 
    if (p == NULL) { 
     fprintf(stderr, "selectserver: failed to bind\n"); 
     exit(2); 
    } 

    freeaddrinfo(ai); // all done with this 

    // listen 
    if (listen(listener, 10) == -1) { 
     perror("listen"); 
     exit(3); 
    } 

    // add the listener to the master set 
    FD_SET(listener, &master); 

    // keep track of the biggest file descriptor 
    fdmax = listener; // so far, it's this one 

    // main loop 
    for(;;) { 
     read_fds = master; // copy it 
     if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) { 
      perror("select"); 
      exit(4); 
     } 

     // run through the existing connections looking for data to read 
     for(i = 0; i <= fdmax; i++) { 
      if (FD_ISSET(i, &read_fds)) { // we got one!! 
       if (i == listener) { 
       // handle new connections 
       addrlen = sizeof remoteaddr; 
       newfd = accept(listener, 
        (struct sockaddr *)&remoteaddr, 
        &addrlen); 
       if (newfd == -1) { 
        perror("accept"); 
       } else { 
        FD_SET(newfd, &master); // add to master set 
        if (newfd > fdmax) { // keep track of the max 
         fdmax = newfd; 
        } 
        printf("selectserver: new connection from %s on " 
         "socket %d\n", 
         inet_ntop(remoteaddr.ss_family, 
          get_in_addr((struct sockaddr*)&remoteaddr), 
          remoteIP, INET6_ADDRSTRLEN), newfd); 
     } 
      } else { 
       // handle data from a client 
       if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) { 
        // got error or connection closed by client 
        if (nbytes == 0) { 
         // connection closed 
         printf("selectserver: socket %d hung up\n", i); 
        } else { 
         perror("recv"); 
        } 
        close(i); // bye! 
        FD_CLR(i, &master); // remove from master set 
       } else { 
        // we got some data from a client 
        for(j = 0; j <= fdmax; j++) { 
         // send to everyone! 
         if (FD_ISSET(j, &master)) { 
          // except the listener and ourselves 
          if (j != listener && j != i) { 
           if (send(j, buf, nbytes, 0) == -1) { 
            perror("send"); 
       } 
       } 
      } 
      } 
     } 

       } // END handle data from client 
      } // END got new incoming connection 
     } // END looping through file descriptors 
    } // END for(;;)--and you thought it would never end! 

    return 0; 
} 

И он будет компилироваться плавно. Теперь моя проблема при исполнении было бы показать это, и я честно понятия не имею, как это исправить (вчера мы только имели класс обсуждение поэтому я в основном нуб о программировании сокетов)

./selectserver 10000 

PORT NO. : 10000 
selectserver: nodename nor servname provided, or not known 

, пожалуйста, медведь со мной благодаря!

+0

Вы действительно думаете, что 'Е (" PORT NO.: % d \ n "," 9034 ");' всегда будут давать полезные результаты? Вы не можете передать переменную string (const char *) в функцию, которая ожидает целое число. Как насчет 'int num =" 1 "+" 2 "'? Конечно, это не сработает. 'int num = 1 + 2;' с другой стороны - совсем другое дело. ;) – enhzflep

+0

'getaddrinfo' не работает таким образом. Прочтите страницу руководства. –

+0

Именно поэтому он использовал тип cast для него 'char * ptrPORT = (char *) &PORT;' так, чтобы он не нарушал параметры 'getaddrinfo' hmmm ... я не знаю, что пошло не так :( – pixiedust27

ответ

1

getaddrinfo принимает указатель на строку с нулевым завершающим символом в качестве второго аргумента.

char* ptrPORT = (char *)&PORT; 

выше утверждение типа литья указатель на int в указатель на символ. Это не меняет того факта, что он все еще указывает на int. Теперь, если вы тщательно подумаете, вы можете видеть, что getaddrinfo не будет знать, как правильно читать ваше значение - это не истинная строка символов с завершающим символом.

Однако argv[1] является нулем строка символов, поэтому мое предложение использовать его как есть, вместо того, чтобы пытаться преобразовать:

char* ptrPORT = argv[1]; 
+0

Спасибо , человек! Это функционально сейчас: D – pixiedust27

+0

приветствуется! Приветствия! – Kalu

0

Аргумент службы принимает как char *, так и int. Однако, вы действительно хотите полагаться на распознавание между char * и int? На странице man enter link description here аргумент службы может быть числом в виде строки. Если для hints.ai_flags установлено значение AI_NUMERICSERV.

Смежные вопросы