2014-03-02 68 views
0

我正在編寫一個非常簡單的服務器應用程序,僅用於測試某些代碼。 創建一個套接字並bind()將其添加到我的本地主機和某個端口後,我想使用select()來知道傳入連接何時到達綁定的套接字。之後,應用程序應該打印消息達到一定長度,然後exit()select()返回時沒有傳入連接

我的問題基本上是如果我只需要使用listen()accept(),那麼當我期待只有一個連接時(請記住這只是爲了測試)。我相信這些功能在這種情況下不需要,只需要接受多個傳入的請求。我錯了嗎?

考慮到上述IDEIA我寫了下面的代碼

int main() 
{ 
    int fd = TCPcreate(atoh("127.0.0.1"), 15000); /*my localhost address*/ 
    char *str = malloc(100); 
    int a; 
    fd_set rfds; 

    FD_ZERO(&rfds); 
    FD_SET(fd,&rfds); 

    a = select(fd+1,&rfds,(fd_set*)NULL,(fd_set*)NULL,(struct timeval*)NULL); 

// printf("select returns %d\nfd = %d\n", a, fd); 
// printf("fd is set? %s\n", FD_ISSET(fd,&rfds) ? "yes" : "no"); 

    a = TCPrecv(fd, str, 100); /*receive at most 100B */ 

// printf("%d\n", a); 
    printf("%s\n", str); 

    close(fd); 
    exit(0); 
} 

TCPcreate()

int TCPcreate(unsigned long IP, unsigned short port) 
{ 
    int fd; 
    struct sockaddr_in address; 

    fd = socket(AF_INET, SOCK_STREAM, 0); 
    if(fd==-1) 
    { 
     return -1; 
    } 

    memset(&address, 0, sizeof(address)); 
    address.sin_family = AF_INET; 
    address.sin_addr.s_addr = htonl(IP); 
    address.sin_port = htons(port); 

    /* struct sockaddr_in is the same size as struct sockaddr */ 
    if(bind(fd, (struct sockaddr*)&address, sizeof(address))==-1) 
    { 
     return -2; 
    } 

    return fd; 
} 

atoh()簡單地返回其在主機字節順序的說法。

當我運行程序時會發生什麼,select()不會阻止等待連接。相反,它會立即返回1。如果我取消了printf()就是我得到的是

select returns 1 
fd = 3 
is set? yes 
-1 
(blank line) 

缺少什麼我在這裏?...

+1

每個連接都需要收聽和接受。沒有辦法避免使用AFAIK。 –

回答

1

如果你看看select() POSIX規範,文件描述符返回已準備好閱讀,寫作或對其有錯誤狀態。這不會列出'listen()會成功的套接字'作爲可檢測條件之一。因此,您需要使用listen()accept();只有在接受連接後,才能在描述符上使用select()

由於Gonçalo Ribeiro筆記,爲select()的規範也說:

如果套接字當前正在偵聽,那麼它應當,如果傳入的連接請求已收到被標記爲可讀,並以accept()通話功能應該完成而沒有阻塞。

這意味着您必須在綁定套接字上完成listen(),但您可以在多個套接字上等待傳入連接。

+1

「如果套接字當前正在偵聽,那麼如果接收到傳入的連接請求,它將被標記爲可讀,並且對accept()函數的調用應該完成而不會阻塞。」 我想'正在偵聽'意味着'listen()'必須在'select()'之前被調用。 –

+0

@GonçaloRibeiro在任何情況下,listen()都不是阻塞調用,所以沒有可以想象的要求事先調用select(),即使它是合法的,而不是。 – EJP

0

如果你想阻止呼叫 - 使用listen()。

選擇的問題在你的代碼中是 - 保留循環中的選擇。因爲這是一個非阻塞的呼叫,它只會檢查有人在那裏聽或不聽。所以,你可以使用循環來檢查多次聽。

相關問題