2014-04-25 133 views
0

我想製作非阻塞式TCP接收器,以便靜默可以定期向服務器發送消息(即每10分鐘更新一次信息)。非阻塞式TCP套接字編程

我在本地機器上測試它。 'return_status'值表示「綁定,接受,連接和寫入」工作正常,但讀取總是返回-1。有人可以解釋一下嗎?謝謝

客戶端的代碼。

#define CONTROLPORT 6000 

int main(void) 
{ 

int control_sock, return_status; 
struct sockaddr_in control_addr; 
socklen_t control_len; 
memset(&control_addr, 0, sizeof(control_addr)); 
char control_message[10]; 

control_sock = socket(AF_INET, SOCK_STREAM, 0); 

control_addr.sin_family = AF_INET; 
control_addr.sin_addr.s_addr = inet_addr("192.168.16.133"); 
control_addr.sin_port = htons(CONTROLPORT); 

return_status = bind(control_sock, (struct sockaddr *) &control_addr, sizeof(control_addr)); 

fcntl(control_sock, F_SETFL, O_NONBLOCK); 

return_status = listen(control_sock, 1); 
    cout << return_status << endl; 
return_status = accept(control_sock, (struct sockaddr *) &control_addr, &control_len); 
    cout << return_status << endl; 

while(1){ 

    return_status = read(control_sock,control_message,sizeof(control_message)); 

    cout << return_status << endl; 

} 







} 

發送方

#define CONTROLPORT 6000 

using namespace std; 

int main(void) 
{ 

int control_sock, return_status; 
struct sockaddr_in control_addr; 
socklen_t control_len; 
memset(&control_addr, 0, sizeof(control_addr)); 
char control_message[10]; 
control_message[10] = 111; 

control_sock = socket(AF_INET, SOCK_STREAM, 0); 

control_addr.sin_family = AF_INET; 
control_addr.sin_addr.s_addr = inet_addr("192.168.16.133"); 
control_addr.sin_port = htons(CONTROLPORT); 

return_status = connect(control_sock, (struct sockaddr *) &control_addr, sizeof(control_addr)); 
    cout << return_status << endl; 



    return_status = write(control_sock,control_message,sizeof(control_message)); 

    cout << return_status << endl; 

}

回答

0

你有你的插槽設置爲非阻塞,因此accept的代碼不會阻塞,直到有一個連接。 accept將返回EAGAIN或EQOULDBLOCK。檢查errno。如果沒有這個檢查,你的代碼將繼續執行read。並且它返回-1(再次檢查errno),因爲連接尚未建立。

您必須使用selectpollepoll來查看非阻塞套接字上的事件。這是要確定是否有人在建立的連接上連接/發送數據。

+0

感謝您的回覆。我刪除了fcntl(control_sock,F_SETFL,O_NONBLOCK);函數「read」仍然返回-1,同時,accept函數返回4.看起來像我設置爲阻止一個,問題依然存在 – user3503150

0

在你的情況下,我不認爲非阻塞服務器是必要的。如果你確實是這個意思,你應該看看select(),epoll和類似的。至於你的代碼,有幾個問題:

  1. accept()在服務器端應該在while循環中。
  2. accept()成功返回接受套接字的描述符,並且此描述符應傳遞給read()
  3. 正如Prabhu的回答所說,您已將套接字設置爲O_NONBLOCK,因此accept()將立即返回。如果沒有連接被接受,則errno將被設置爲EAGAINEWOULDBLOCK

修改後的代碼:

int main(void) 
{ 
    int control_sock, return_status; 
    struct sockaddr_in control_addr; 
    socklen_t control_len; 
    memset(&control_addr, 0, sizeof(control_addr)); 
    char control_message[10]; 

    control_sock = socket(AF_INET, SOCK_STREAM, 0); 

    control_addr.sin_family = AF_INET; 
    control_addr.sin_addr.s_addr = inet_addr("192.168.7.134"); 
    control_addr.sin_port = htons(CONTROLPORT); 

    return_status = bind(control_sock, (struct sockaddr *) &control_addr, sizeof(control_addr)); 

    //fcntl(control_sock, F_SETFL, O_NONBLOCK); 

    return_status = listen(control_sock, 1); 
    cout << return_status << endl; 
    while(1){ 
     return_status = accept(control_sock, (struct sockaddr *) &control_addr, &control_len); 
     cout << return_status << endl; 


     return_status = read(return_status,control_message,sizeof(control_message)); 

     cout << return_status << endl; 

    } 
} 
+0

這是程序的一部分,我想設置非阻塞所以程序可以進入下一個廣播功能,基本上我想讀取TCP數據(如果有的話),然後發送UDP數據,謝謝你的進一步提示 – user3503150

+0

更不用說阻塞和非阻塞,最重要的部分是你應該'read()'描述符**,accept()'在服務器端返回** – jfly

+0

感謝你對這個問題的理解,哦,上帝,我是如何讀取返回狀態的。 – user3503150

0

如果你打算從事非阻塞套接字編程,你必須明白,閱讀()將會返回-1並設置errno爲EAGAIN/EWOULDBLOCK,當沒有東西要讀時,並使用select()來告訴你它何時不會。

NB 4是在Unix,Solaris,HP-UX,AIDA,Linux中的有效套接字FD ...