2017-03-13 41 views
0

我有这个ftserver.c程序,它正在实现一个文件传输服务器,它监听客户端,然后通过数据连接响应客户端请求。现在它可以工作,但我有硬编码数据连接的主机名和端口号。 portnumber由客户端提供,服务器应该能够从客户端的控制连接中获取主机名。如何分配客户端连接的主机名和端口号?

参考文献:http://beej.us/guide/bgnet/output/html/multipage/getaddrinfoman.html

我如何分配的主机名和端口号动态?谢谢。

void error(const char *msg) 
{ 
perror(msg); 
exit(1); 
} 

void startup(int portNumber); 
void setupData(char* portNum); 

int sockfd, newsockfd, datasock, portno; 
char buffer[256]; socklen_t clilen; 
struct sockaddr_in serv_addr, cli_addr, port_addr; 
struct addrinfo hints, *servinfo, *p; 
char ipstr[1000]; 
struct in_addr ipAddr; 
struct sockaddr_in *s; 

int main(int argc, char *argv[]){ 
    int n; char* dataport; char * token; char filename[100]; 

    if (argc < 2) { 
     fprintf(stderr,"ERROR, no port provided\n"); 
     exit(1); 
    } 
    portno = atoi(argv[1]); 

    startup(portno); 

    n = read(newsockfd,buffer,255); 
    if (n < 0) error("ERROR reading from socket"); 
    printf("Here is the message: %s\n",buffer); 

    token = strtok(buffer, " "); 

    //if client requested a list, setup data connection and send it 
    if (strcmp(token, "-l") == 0){ 
     token = strtok(NULL, " "); 
     printf("the token is %s\n", token); 
     //dataport = atoi(token); 
     dataport = token; 
     setupData(dataport); 
     //sendList(dataport); 
    } 
    //if client requested a file, setup data connection and send it 
    else if (strcmp(token, "-g") == 0){ 
     token = strtok(NULL, " "); 
     //filename = *token; 
     token = strtok(NULL, " "); 
     //dataport = atoi(token); 
     printf("the data port is %d\n", dataport); 
     //setupData(dataport); 
     //sendFile(filename, dataport); 
    } 
    else { 
     n = write(newsockfd,"not a valid command",19); 
     if (n < 0) error("ERROR writing to socket"); 
    } 

    //close sockets for connection P 
    close(datasock); 
    close(newsockfd); 
    close(sockfd); 
    return 0; 
} 

void startup(int portNumber) 
{ 

sockfd = socket(AF_INET, SOCK_STREAM, 0); 
if (sockfd < 0) 
    error("ERROR opening socket"); 
bzero((char *) &serv_addr, sizeof(serv_addr)); 

serv_addr.sin_family = AF_INET; 
serv_addr.sin_addr.s_addr = INADDR_ANY; 
serv_addr.sin_port = htons(portNumber); 
if (bind(sockfd, (struct sockaddr *) &serv_addr, 
      sizeof(serv_addr)) < 0) 
      error("ERROR on binding"); 
listen(sockfd,5); 
clilen = sizeof(cli_addr); 
newsockfd = accept(sockfd, 
      (struct sockaddr *) &cli_addr, 
      &clilen); 

if (newsockfd < 0) 
     error("ERROR on accept"); 
bzero(buffer,256); 
} 

void setupData(char* portNum){ 
    int rv; 

    const char* name = "localhost"; 
    char s[1000]; 

    memset(&hints, 0, sizeof (hints)); 
    hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6 
    hints.ai_socktype = SOCK_STREAM; 

    if ((rv = getaddrinfo(name, "30024", &hints, &servinfo)) != 0) { 
     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 
     exit(1); 
    } 

    // loop through all the results and connect to the first we can 
    for(p = servinfo; p != NULL; p = p->ai_next) { 
     if ((datasock = socket(p->ai_family, p->ai_socktype, 
       p->ai_protocol)) == -1) { 
      perror("socket"); 
      continue; 
     } 

     if (connect(datasock, p->ai_addr, p->ai_addrlen) == -1) { 
      perror("connect"); 
      close(sockfd); 
      continue; 
     } 

     break; // if we get here, we must have connected successfully 
    } 

    if (p == NULL) { 
     // looped off the end of the list with no connection 
     fprintf(stderr, "failed to connect\n"); 
     exit(2); 
    } 

    printf("data connection setup successful\n"); 
} 
+0

现在,如果我只是把“端口编号”,而不是“30024”来的getaddrinfo它给人不支持ai_socktype错误 – Sana

+1

你为什么要叫'getaddrinfo()将一个servname'如果你已经获得客户端主机名和端口? –

+0

现在我把它硬编码为“localhost”和“30024”,但我想使它成为动态的,这样我的单独客户端代码的参数就可以指定数据端口来启动数据连接并将信息发送到该端口。我尝试从第一个控制连接(在startup()中创建)保存客户端主机名,然后将其应用于第二个连接,但无法使其工作。 – Sana

回答

0

我已经解决了这个问题。通过使用设置数据连接的简化版本,不使用getaddrinfo()并使用hostname_to_ip转换函数。参考:http://www.linuxhowtos.org/data/6/client.c

int setupData(char* hostname, char* portNum){ 
    int sock_fd; char ip[100]; 
    struct sockaddr_in srv_addr; 

    memset(&srv_addr, 0, sizeof(srv_addr)); /* zero-fill srv_addr structure*/ 
    /* create a client socket */ 
    sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    srv_addr.sin_family = AF_INET; /* internet address family */ 
    /* convert command line argument to numeric IP */ 
    hostname_to_ip(hostname, ip); 
    printf("%s resolved to %s" , hostname , ip); 

    if (inet_pton(AF_INET, ip, &(srv_addr.sin_addr)) < 1) 
    { 
     printf("Invalid IP address\n"); 
     exit(EXIT_FAILURE); 
    } 
    srv_addr.sin_port = htons(atoi(portNum)); 
    if(connect(sock_fd, (struct sockaddr*) &srv_addr, sizeof(srv_addr)) < 0) 
    { 
     perror("connect error"); 
     exit(EXIT_FAILURE); 
    } 

    return sockfd; 
} 
相关问题