2014-07-01 49 views
2

我正嘗試使用TCP將客戶端連接到服務器。我想我的客戶端正確地執行了他的工作,但服務器無法接受連接。 這裏是我的代碼:錯誤:嘗試接受來自客戶端的連接時參數無效

SERVER:

int main(int argc, char *argv[]) 
{ 
    int port, sock, newsock, thread_pool_size, queue_size; 
    struct sockaddr_in server, client; 
    struct sockaddr *serverptr = (struct sockaddr *)&server; 
    struct sockaddr *clientptr = (struct sockaddr *)&client; 
    struct hostent *rem; 
    socklen_t clientlen; 
    pthread_t thr; 
    int i, err, status; 

    if(argc != 7) 
    { 
     printf("Usage: ./dataServer -p <port> -s <thread_pool_size> -q <queue_size>\n"); 
     exit(1); 
    } 

    for(i=1; i<argc; i++) 
    { 
     if(strcmp(argv[i], "-p") == 0) 
     { 
      port = atoi(argv[++i]); 
     } 

     else if(strcmp(argv[i], "-s") == 0) 
     { 
      thread_pool_size = atoi(argv[++i]); 
     } 

     else if(strcmp(argv[i], "-q") == 0) 
     { 
      queue_size = atoi(argv[++i]); 
     } 

     else 
     { 
      printf("Wrong Input < %s >\n", argv[i]); 
      exit(1); 
     } 
    } 

    printf("%d %d %d\n", port, thread_pool_size, queue_size); 

    /* Create socket */ 
    if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) 
    { 
     perror_exit("socket"); 
    } 

    server.sin_family = AF_INET;  /* Internet domain */ 
    server.sin_addr.s_addr = htonl(INADDR_ANY); 
    server.sin_port = htons(port);  /* The given port */ 

    /* Bind socket to address */ 
    if(bind(sock, serverptr, sizeof(server)) < 0) 
    { 
     perror_exit("bind"); 
    } 

    /* Listen for connections */ 
    if(listen(sock, 5) < 0) 
    { 
     perror_exit("listen"); 
    } 

    printf("Listening for connections to port %d\n", port); 

    while(1) 
    { 
     /* accept connection */ 
     if((newsock = accept(sock, clientptr, &clientlen)) < 0) 
     { 
      //HERE IS THE PROBLEM 
      perror_exit("accept"); 
     } 

     if((rem = gethostbyaddr((char *) &client.sin_addr.s_addr, sizeof(client.sin_addr.s_addr), client.sin_family)) == NULL) 
     { 
      herror("gethostbyaddr"); 
      exit(1); 
     } 

     printf("Accepted connection from %s\n", rem->h_name); 

     close(sock); 

     if((err = pthread_create(&thr, NULL, (void*)thread_f, (int *)newsock))) 
     { 
      perror_exit("pthread_create"); 
      exit(1); 
     } 

     if((err = pthread_join(thr, (void **) &status))) 
     { 
      perror_exit("pthread_join"); 
      exit(1); 
     } 

     close(newsock); 
    } 

    return 0; 
} 

客戶:

int main(int argc, char *argv[]) 
{ 
    int port, sock, i; 
    char buf[30]; 
    struct sockaddr_in server; 
    struct sockaddr *serverptr = (struct sockaddr*)&server; 
    struct hostent *rem; 
    char server_ip[15]; 

    if(argc != 7) 
    { 
     printf("Usage: ./remoteClient -i <server_ip> -p <server_port> -d <directory>\n"); 
     exit(1); 
    } 

    for(i=1; i<argc; i++) 
    { 
     if(strcmp(argv[i], "-i") == 0) 
     { 
      strcpy(server_ip, argv[++i]); 
     } 

     else if(strcmp(argv[i], "-p") == 0) 
     { 
      port = atoi(argv[++i]); 
     } 

     else if(strcmp(argv[i], "-d") == 0) 
     { 
      strcpy(buf, argv[++i]); 
     } 

     else 
     { 
      printf("Wrong Input < %s >\n", argv[i]); 
      exit(1); 
     } 
    } 

    printf("%s %d %s\n", server_ip, port, buf); 

    /* Create socket */ 
    if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) 
    { 
     perror_exit("socket"); 
    } 

    /* Find server address */ 
    if((rem = gethostbyname(server_ip)) == NULL) 
    { 
     herror("gethostbyname"); exit(1); 
    } 

    server.sin_family = AF_INET; 
    memcpy(&server.sin_addr, rem->h_addr, rem->h_length); 
    server.sin_port = htons(port); 

    /* Initiate connection */ 
    if(connect(sock, serverptr, sizeof(server)) < 0) 
    { 
     perror_exit("connect"); 
    } 

    if (write(sock, buf, sizeof(buf)) < 0) 
    { 
     perror_exit("write"); 
    } 

    close(sock); 

    printf("ok\n"); 

    return 0; 
} 

如果你想運行它們:

./dataServer -p 12500 -s 2 -q 2

./remoteClient -i localhost -p 12500 -d ./dir/file_1

不要介意我的其他代碼。 你能幫忙嗎?提前致謝!

+0

無關的評論,但我必須說,很高興看到代碼與一些錯誤處理:) –

回答

3

acceptman page(我的重點)

The addrlen argument is a value-result argument: the caller must initialize it to contain the size (in bytes) of the structure pointed to by addr; on return it will contain the actual size of the peer address.

你傳遞一個未初始化的變量。您需要初始化這個先給緩衝區clientptr點的大小

socklen_t clientlen = sizeof(client); 

在這之後,你應該招行

close(sock); 

過去你while循環結束。您的下一個錯誤是由在您關閉的手柄上運行的第二次迭代循環引起的。

+0

我做了clientlen的初始化,現在我有另一個錯誤:「錯誤的文件描述符」。這裏奇怪的是,我的程序首先打印「從本地主機接受連接」,然後向我顯示錯誤。它如何繼續,然後停止? –

+0

@a_user我已經更新了我的答案以涵蓋第二點 – simonc

+0

@simonic我愛你。非常感謝。一切都很好! –

相關問題