2014-10-08 49 views
0

我正在用C寫一個TCP客戶端。 以下幾個教程我寫了我的代碼,但它只能接受到服務器的第一個連接。第一次接受TCP後的Linux服務器鎖定

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> //inet_addr for INADDR_ANY 
#include <string.h> //for splitting (strtok) 
#include <pthread.h> //thread library 
#include <time.h> 
#include <unistd.h> //for function close() 

void* SocketHandler(void*); 


int main(void) { 
    //socket parameters 
    int server_socket_desc; 
    int clientAddressLength = sizeof(struct sockaddr_in); 
    struct sockaddr_in server_addr, client_addr; 

    const unsigned short int PORT_NUMBER = 8963; 
server_socket_desc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if (server_socket_desc < -1) { 
     printf("Could not create socket"); 
    } 
    puts("Socket created"); 

    //Prepare the sockaddr_in structure 
    server_addr.sin_family = AF_INET; //it should be always set to AF_INET 
    //set the server address 
    server_addr.sin_addr.s_addr = inet_addr("192.168.123.240"); 
    //server_addr.sin_addr.s_addr = inet_addr("31.185.101.35"); 
    //server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    server_addr.sin_port = htons(PORT_NUMBER); 

    //Bind 
    if (bind(server_socket_desc, (struct sockaddr *) &server_addr, 
      sizeof(server_addr)) < 0) { 
     //print the error message 
     perror("bind failed. Error"); 
     return 1; 
    } 
    puts("bind done"); 

    //Listen 
    listen(server_socket_desc, 10); 

    //Accept and incoming connection 
    puts("Waiting for incoming connections..."); 

    //accept connection from an incoming client 
    while (1) { 
     int *temp_socket_desc = (int*) malloc(sizeof(int)); 
     if ((*temp_socket_desc = accept(server_socket_desc, 
       (struct sockaddr *) &client_addr, 
       (socklen_t*) &clientAddressLength)) != -1) { 

      printf("----------\nConnection accepted \n"); 
      sleep(1); 
      pthread_t thread_id; 
      int *client_socket_desc = (int*) malloc(sizeof(int)); 
      client_socket_desc = temp_socket_desc; 

      pthread_create(&thread_id, NULL, &SocketHandler, 
        (void*)  client_socket_desc); 
      //if thread has not terminated, pthread_detach() shall not cause it to terminate 
      pthread_detach(thread_id); 
      puts("handler assigned"); 

     } else 
      puts("connection refused"); 

    } 

    close(server_socket_desc); 
    //mysql_close(mysql_conn); 
    return 0; 
} 

/* 
* This will handle connection for each client 
* */ 
void* SocketHandler(void* lp) { 
    int *csock = (int*) lp; 

    char buffer[128]; 
    int buffer_len = 128; 
    int bytecount; 
    memset(buffer, 0, buffer_len); 
    if ((bytecount = read(*csock, buffer, buffer_len) == -1)) { 
     fprintf(stderr, "Error receiving data\n"); 
     close(*csock); 
     return 0; 
    } 
    printf("Received bytes %d\nReceived string \"%s\"\n", bytecount, buffer); 

    close(*csock); 
    free(csock); 
    puts("exiting thread"); 
    //pthread_exit(0); 
    return 0; 
} 

我暫時解決了插入睡眠()的問題後while循環,但它是一個非常糟糕的解決方案。 有人可以解釋爲什麼代碼在沒有睡眠的情況下工作嗎?

+0

你的代碼不會編譯,你有多個int * client_socket_desc定義。請正確更新代碼並粘貼客戶端和服務器的輸出 – 4pie0 2014-10-08 14:20:46

回答

0

有一個在client_socket_desc處理一個問題:

你分配它只有一次。所有線程都會得到相同的指針。 因此,稍後接受將覆蓋較早線程的套接字描述符值。

試試下面的變化,爲每個線程分配自己的內存塊:

int fd = accept(server_socket_desc, (struct sockaddr *) &client_addr, (socklen_t*)     
       &clientAddressLength) 
if (fd != -1) 
{   
    pthread_t thread_id; 
    int *client_socket_desc = malloc(sizeof(int)); 

    *client_socket_desc = fd; 

    pthread_create(&thread_id, NULL, &SocketHandler,(void*) client_socket_desc); 
    ... 

或課程,你必須添加錯誤handlings的malloc和在pthread_create。 還可以在不再需要時釋放分配的內存。

我不理解,爲什麼在while循環下面的代碼:在客戶端處理線程

if(send(*client_socket_desc,buffer,1,MSG_NOSIGNAL)>0) 
{ 
    puts("closing client socket"); 
    close(*client_socket_desc); 
} 

關閉客戶端套接字。

+0

坦克你的答案,現在我已經更清楚地知道線程如何工作,但代碼仍然只接受第一個連接我正在更新我的代碼在第一篇文章 – Niles 2014-10-08 14:21:10

相關問題