2011-10-22 41 views
0

我想實現一個UDP套接字服務器(在Linux下使用c)。當服務器收到來自客戶端的新消息時,我想避免掛起客戶端。 (我不想要使用線程)UDP套接字編程 - 在recev上的fork服務器

的問題是,服務器繼續等待(在recvfrom函數塊),但是,當所述客戶端發送所述第一消息,所述服務器保持分叉許多工藝(看起來它正在接收不超過一次或類似的客戶端的詳細消息被髮送很多次,真的我不知道問題出在哪裏)

服務器:

// socket file descriptor (socket descriptor) 
int socket_fd; 
// serverTCP and client addresses 
struct sockaddr_in server_addr, client_addr; 
socklen_t sin_size; 
int bytes_read; 
char recv_data[1024]; 

// create the socket 
if ((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { 
    perror("UDP Server: ERROR while creating the socket.\n"); 
    exit(1); 
} 

// define the socket address associated with the created socket 
// set the server address and port number 

// set the binding of the serverUDP socket 
printf("\nUDP Server: server socket binding..."); 
if (bind(socket_fd, (struct sockaddr *) &server_addr, sizeof(struct sockaddr)) == -1) { 
    perror("UDP Server: ERROR while binding the socket.\n"); 
    exit(1); 
} 
printf("\nUDP Server: done binding."); 

sin_size = sizeof(struct sockaddr); 
// block and wait for connection request 
int pid; // process ID for forking new serverUDP process 
while (1) { 
    printf("\nUDP Server: waiting for connection..."); 
    bytes_read = recvfrom(socket_fd, recv_data, 1023, 0, 
      (struct sockaddr *) &client_addr, &sin_size); 

    // a connection has been established 
    recv_data[bytes_read] = '\0'; 
    printf("\nUDP Server: received -> %s", recv_data); 
    pid = fork(); 

    if (pid < 0) { 
     perror("UDP Server: ERROR while forking new process.\n"); 
     exit(1); 
    } 
    // check if the process ID is zero 
    if (pid == 0) { 
     // we are now inside the new forked process 
     char result[50]; 
     int len = sprintf(result, "%d", server_parse_command(recv_data)); 
     len = sendto(socket_fd, result, len, 0, 
       (struct sockaddr *) &client_addr, sin_size); 
     close(socket_fd); 
     exit(0); 
    } 
} 

客戶:

int socket_fd; 
struct sockaddr_in server_addr; 
struct hostent *host; 
host = gethostbyname("127.0.0.1"); 

// create the socket 
if ((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { 
    perror("UDP Client: ERROR while creating the socket.\n"); 
    exit(1); 
} 
// define the socket address associated with the created socket 
    // set the client address and port number 

// send messages to the server socket 
int count; 
char buffer[128]; 
while (1) { 
    socklen_t sin_size = sizeof(struct sockaddr); 
    // read message to send to the server and set count to the length of the message 

    count = sendto(socket_fd, buffer, count, 0, 
      (struct sockaddr *) &server_addr, sizeof(struct sockaddr)); 
    if (count < 0) { 
     perror("UDP Client: ERROR while writing message to server socket.\n"); 
     exit(1); 
    } 
    bzero(buffer, 128); 
    count = recvfrom(socket_fd, buffer, 127, 0, 
      (struct sockaddr *) &server_addr, &sin_size) ; 

    if (count < 0) { 
     perror("UDP Client: ERROR while reading response from server socket.\n"); 
     exit(1); 
    } 
    buffer[count] = '\0'; 
    printf("\nUDP Client: received response -> %s", buffer); 
    close(socket_fd); 
} 

對不起,長代碼。

+2

每次接收時間UDP數據包似乎是極端矯枉過正派生一個新的進程..如果你的服務器每秒接收到不平凡的數據包數量,那將是非常低效的。解決懸掛客戶問題既不必要也不足以解決問題。如果您的客戶因爲沒有及時收到回覆數據包而被掛起,那麼您應該在客戶端解決該問題(例如,通過使用select()或poll()來超時,而不僅僅是阻止接收()調用) –

回答

1

(通過在編輯OP回答見Question with no answers, but issue solved in the comments (or extended in chat)

的OP寫道:

我終於解決了這個問題,我只想把我的解決方案如果有人面對它。

在服務器實現和while(1)循環內。 檢查如果接收到的bytes_read緩存> 0做任何事情之前,否則繼續循環,所以這將是這樣的:

while (1) { 
    printf("\nUDP Server: waiting for connection..."); 
    bytes_read = recvfrom(socket_fd, recv_data, 1023, 0, 
      (struct sockaddr *) &client_addr, &sin_size); 

    if (bytes_read > 0) { 
       // a connection has been established 
      recv_data[bytes_read] = '\0'; 
       printf("\nUDP Server: received -> %s", recv_data); 
      pid = fork(); 

      if (pid < 0) { 
       perror("UDP Server: ERROR while forking new process.\n"); 
       exit(1); 
      } 
      // check if the process ID is zero 
      if (pid == 0) { 
       // we are now inside the new forked process 
       char result[50]; 
       int len = sprintf(result, "%d", server_parse_command(recv_data)); 
       len = sendto(socket_fd, result, len, 0, 
       (struct sockaddr *) &client_addr, sin_size); 
       close(socket_fd); 
       exit(0); 
      } 
    } 
}