簡體   English   中英

* nix和C ++編寫非阻塞套接字服務器

[英]*nix & C++ writing a non-blocking socket server

將阻塞套接字服務器重寫為非阻塞版本時遇到一些問題。 實際上,我什至似乎都無法再連接套接字,我在今天的大部分時間里一直在搜尋,並嘗試在這里和那里找到的不同解決方案,但是它們似乎都無法正常工作...當前我的服務器循環只是保持超時select()調用,不接受任何新的套接字。 客戶端套接字似乎在某種程度上已連接,因為如果我啟動它,它將阻止嘗試寫入,並且如果我關閉服務器,它將通知連接已被對等方重置。

以下假設是否正確? 對於非阻塞服務器,我通常應該打開套接字,然后將其標志設置為非阻塞,將其綁定,然后開始調用read讀取文件描述符的select並等待其填充? 我需要刪除一直無休止地等待的舊阻塞“ accept()”調用。如果我嘗試調用accept,它將在我身上變成-1。

這是我正在嘗試的相關代碼

fd_set incoming_sockets;
....
int listener_socket, newsockfd, portno;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
....
listener_socket = socket(AF_INET, SOCK_STREAM, 0); //get socket handle
int flags = fcntl(listener_socket, F_GETFL, 0);
if( fcntl(listener_socket, F_SETFL, flags | O_NONBLOCK) < 0 )
    log_writer->write_to_error_log("Error setting listening socket to non blocking", false);
memset(&serv_addr, 0, sizeof(struct sockaddr_in));

serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
....
if (bind(listener_socket, (struct sockaddr *) &serv_addr,
        sizeof(struct sockaddr_in)) < 0)
{
    log_writer->write_to_error_log("Unable to bind socket, aborting!", true);
}
....
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;

int ready_sockets = 0;

listen(listener_socket,1);

FD_ZERO(&incoming_sockets); 
FD_SET(listener_socket, &incoming_sockets); 

while(true)
{

ready_sockets = select(listener_socket + 1 , &incoming_sockets, (fd_set * ) 0, (fd_set * ) 0, &timeout  );

if(ready_sockets == 0)
    {
        //I loop here now for ever
        std::cout << "no new sockets available, snooze 2\n";
        sleep(2);
    } else
    {
    std::cout << "connection received!\n";

由於您沒有顯示整個循環,因此我不知道稍后是否執行此操作,但是您應該在每次調用select之前初始化描述符集和超時結構。

您應該在循環移動fd_zero()fd_set()宏,select實際上會更改 fd_sets中的位掩碼(以及超時值)。 在每次迭代時重新初始化它們。 還要檢查選擇返回-1和相關的錯誤號(EPIPE ...)

while(true)
{

FD_ZERO(&incoming_sockets); 
FD_SET(listener_socket, &incoming_sockets); 



ready_sockets = select(listener_socket + 1 , &incoming_sockets, (fd_set * ) 0, (fd_set * ) 0, &timeout  );

if(ready_sockets == 0)
    {
      ... }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM