TCP 代理接收數據阻塞問題解決方案

TCP 代理轉發數據示意圖如下:

                 Client <--------------------------->TCP Proxy <---------------------------->Server

Client 先發起請求,代理在接收到connect 請求之後,新建一個線程處理該客戶端的轉發需求。

在調用recv 接收數據時,有時程序會一直阻塞在那裏,原因是socket 默認是阻塞模式,而當前沒有數據可接收時會一直等待。還有另一個情況:調用一次recv, 數據並沒有接收完全,再調用recv 時仍然會阻塞。在應用層除非明確知道結束標誌或者數據長度,否則沒法知道數據是否已接收完畢。

 

正確的做法是輪詢,使用select 實現,當某個socket處於可以接收時,就去讀取數據,然後用另一個socket 轉發。

實現的方法:

fd_set readfds;

TIMEVAL tv;

tv.tv_usec = 100;

tv.tv_sec = 1;

do{

    FD_ZERO(&readfds);

    FD_SET(socket_client, &readfds);

    FD_SET(socket_server, &readfds);

    int n = select(0, &readfds, NULL, NULL, &tv);

    if (n>0)  //有數據可讀
    {
        if (FD_ISSET(socket_client, &readfds))
        {

            int nr = recv(socket_client, buffer, buffer_size, 0);

            if (nr > 0)

                int ns = send(socket_server, buffer, nr, 0);
        }

     
        if (FD_ISSET(socket_server, &readfds))
        {
            int nr = recv(socket_server, buffer, buffer_size, 0);
            if (nr > 0)
                int ns = send(socket_client, buffer, nr, 0);

        }
    }

    else if (n == SOCKET_ERROR) //選擇錯誤
    { 
         printf("select error");
         break;
    }

    else  //超時,Sleep 1s
    {
        Sleep(1000);
    }

}while(true);

參考:

https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-select

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章