2013-05-31 12 views
1
  1. 客戶

事實上,我的客戶不的recv和處理數據從服務器發送,只需連接到我的服務器。插座設置與O_NONBLOCK,但似乎有時發送數據時調用線程還是進入睡眠

int netif_msg_client_socket_create(char *sockpath) 
    { 

     int addrlen, retval; 
     int sockfd; 
     struct sockaddr_un serv; 

     sockfd = socket(AF_UNIX, SOCK_STREAM, 0); 
     if(sockfd < 0) { 
    PR_ERROR(NETIF_MSG_M, " fatal failure, client msg socket, error is %s, %s %u\n", strerror(errno), __FILE__, __LINE__); 
      return -1; 
     } 

     /* Make client socket. */ 
     memset (&serv, 0, sizeof (struct sockaddr_un)); 
     serv.sun_family = AF_UNIX; 
     strncpy (serv.sun_path, sockpath, strlen(sockpath)); 

     addrlen = sizeof (serv.sun_family) + strlen(serv.sun_path); 

     retval = connect(sockfd, (struct sockaddr*)&serv, addrlen); 
     if(retval < 0) 
     { 
      PR_ERROR(NETIF_MSG_M, " fatal failure, client msg connect, error is %s, %s %u\n", strerror(errno), __FILE__, __LINE__); 
      close(sockfd); 
      return -1; 
     } 

     fcntl(sockfd, F_SETFL, O_NONBLOCK); 

     return sockfd; 
    } 

2.Server

但我的服務器將嘗試一些數據連續發送到客戶端。

int netif_msg_server_socket_create(char *sockpath) 
    { 

     int addrlen, retval; 
     int sockfd; 
     struct sockaddr_un serv; 

     /* First of all, unlink existing socket */ 
     unlink (sockpath); 

     sockfd = socket(AF_UNIX, SOCK_STREAM, 0); 
     if(sockfd < 0) 
      return -1; 

     fcntl(sockfd, F_SETFL, O_NONBLOCK); 

     /* Make server socket. */ 
     memset (&serv, 0, sizeof (struct sockaddr_un)); 
     serv.sun_family = AF_UNIX; 
     strncpy (serv.sun_path, sockpath, sizeof(serv.sun_path)-1); 

     addrlen = sizeof (serv.sun_family) + strlen(serv.sun_path); 
     //printf("sizeof(serv) == %d, addrlen == %d.\r\n", sizeof(serv), addrlen); 

     retval = bind (sockfd, (struct sockaddr *) &serv, addrlen); 
     if (retval < 0) 
     { 
      close (sockfd); /* Avoid sd leak. */ 
      return -1; 
     } 

     retval = listen (sockfd, 20); 
     if (retval < 0) 
     { 
      close (sockfd); /* Avoid sd leak. */ 
      return -1; 
     } 

     return sockfd; 
    } 
  1. 我的服務器使用選擇併成功地接受來自我的客戶端的連接。
  2. 當我的服務器發送了412個數據包(每個96字節)後,服務器似乎在發送。

鍵代碼:

printf("Try to send packet(%d bytes) to clientfd %d.\n", MSGCB_DLEN(msgcb), client->acpt_fd); 

    retval = send(client->acpt_fd, msgcb->data_ptr, MSGCB_DLEN(msgcb), 0); 
    if(retval != MSGCB_DLEN(msgcb)) 
    { 
     printf("Send netif notify msg failed[%d].\n", retval); 
    } else { 
    printf("Send netif notify msg succeeded.\n"); 
    } 

後412的數據包發送到我的客戶端和 「嘗試......」 outputed,沒事的推移,既不是 「...失敗」,也不是」 ......成功「輸出。

  1. 我使用getsockopt來取SO_RCVBUF和SO_SNDBUF,每個都有大約100000Bytes。

  2. 我不知道爲什麼,需要你的幫助,謝謝!

+0

你在正確的軌道上。所有套接字IO都應該是非阻塞的,即使您在輪詢以查看是否有數據要讀取和寫入,也不能保證在您檢查它時檢查它,所以如果您不是非 - 阻擋,你可能會阻止。 – xaxxon

回答

4

如果你想連接到客戶端是非阻塞服務器套接字,則必須專門設置是從accept()返回到非阻隔新的插座。您的代碼只會將偵聽套接字設置爲非阻塞。

+0

非常感謝,我會嘗試。 – dejunl

1

您可以使用MSG_DONTWAIT國旗在最後一個參數與send實現非阻塞I/O。

retval = send(client->acpt_fd, msgcb->data_ptr, MSGCB_DLEN(msgcb), 
        MSG_DONTWAIT); 

執行非阻塞I/O時,需要檢測何時返回值指示您重試操作。

if (retval < 0) { 
     if (errno == EAGAIN) { 
      /* ... handle retry of send laster when it is ready ... */ 
     } else { 
      /* ... other error value cases */ 
     } 
    }