亚洲欧美日韩熟女|做爱高潮视频网址|国产一区二区三级片|国产Av中文字幕www.性色av|亚洲婷婷永久免费|国产高清中文字幕|欧美变态网站久re视频精品|人妻AV鲁丝第一页|天堂AV一区二区在线观看|综合 91在线精品

在阻塞和非阻塞模式下,connect函數(shù)的行為

2023-05-19


在阻塞和非阻塞模式下,connect函數(shù)的行為


當(dāng)socket在使用堵塞方式時(shí),connect如果網(wǎng)絡(luò)環(huán)境不好,函數(shù)會(huì)被堵塞,直到有明確的結(jié)果才會(huì)回來(lái),可能要等一會(huì)兒,影響感覺(jué),


為解決這一問(wèn)題,我們使用它。異步connect技術(shù)


  1. 建立socket,將socket將其設(shè)置為非阻塞模式
  2. 調(diào)用connect此時(shí)不管函數(shù)connect函數(shù)是否連接成功,將立即返回,如果返回-1,則不一定意味著連接錯(cuò)誤,如果此時(shí)錯(cuò)誤碼為EINPROGRESS表示正在嘗試連接
  3. 調(diào)用select在規(guī)定的時(shí)間內(nèi)判斷函數(shù)。socket是否可以寫(xiě),可以寫(xiě)表示連接成功,相反,連接失敗
    以上流程代碼
#include  
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define SERVER_ADDRESS  "127.0.0.1"
#define SERVER_PORT     3000
#define SEND_DATA       "helloworld"

int main(int argc, char* argv[])
{
    創(chuàng)建一個(gè)socket
    int clientfd = socket(AF_INET, SOCK_STREAM, 0);
    if (clientfd == -1)
    {
        std::cout << "create client socket error." << std::endl;
        return -1;
    }
///將clientfd設(shè)置為非阻塞方式
int oldSocketFlag = fcntl(clientfd, F_GETFL, 0);
int newSocketFlag = oldSocketFlag | O_NONBLOCK;
if (fcntl(clientfd, F_SETFL,  newSocketFlag) == -1)
{
close(clientfd);
std::cout << "set socket to nonblock error." << std::endl;
return -1;
}
//2.連接服務(wù)器
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(SERVER_ADDRESS);
serveraddr.sin_port = htons(SERVER_PORT);
for (;;)
{
int ret = connect(clientfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
if (ret == 0)
{
std::cout << "connect to server successfully." << std::endl;
close(clientfd);
return 0;
} 
else if (ret == -1) 
{
if (errno == EINTR)
{
//connect 信號(hào)中斷了動(dòng)作,再次嘗試connect
std::cout << "connecting interruptted by signal, try again." << std::endl;
continue;
} 
else if (errno == EINPROGRESS)
{
//正在嘗試連接
break;
} 
else
{
//的確出了問(wèn)題,
close(clientfd);
return -1;
}
}
}
fd_set writeset;
FD_ZERO(&writeset);
FD_SET(clientfd, &writeset);
struct timeval tv;
tv.tv_sec = 3;  
tv.tv_usec = 0;
使用select函數(shù)來(lái)判斷socket是否可以寫(xiě)作。
if (select(clientfd   1, NULL, &writeset, NULL, &tv) == 1)
{
std::cout << "[select] connect to server successfully." << std::endl;
} 
else 
{
std::cout << "[select] connect to server error." << std::endl;
}

close(clientfd);
return 0;
}

首先先用nc啟動(dòng)服務(wù)器程序并執(zhí)行指令


nc -v -l -n 0.0.0.0 3000

然后運(yùn)行程序,我使用的clion


關(guān)閉服務(wù)器,重新啟動(dòng)客戶(hù)端,看看結(jié)果,或者


為什么不能連接也會(huì)導(dǎo)出相同的結(jié)果?理由如下:


  • 一個(gè)Windows,socket在建立連接之前,我們使用它。select檢驗(yàn)是否可以寫(xiě),是否可以得到正確的結(jié)果,即不能寫(xiě);連接成功后,在檢驗(yàn)中,就會(huì)變成可寫(xiě)的。
  • 最后一個(gè)是Linuxsocket使用前未建立連接,select函數(shù)檢驗(yàn)是否可以寫(xiě),我們也可以得到可以寫(xiě)的結(jié)果。因此,在Linux上,我們不僅要使用它。select檢驗(yàn)socket是否可以寫(xiě)還要用getsocketopt檢驗(yàn)socket這個(gè)時(shí)候是否有錯(cuò)誤
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define SERVER_ADDRESS "127.0.0.1"
#define SERVER_PORT     3000
#define SEND_DATA       "helloworld"

int main(int argc, char* argv[])
{
    創(chuàng)建一個(gè)socket
    int clientfd = socket(AF_INET, SOCK_STREAM, 0);
    if (clientfd == -1)
    {
        std::cout << "create client socket error." << std::endl;
        return -1;
    }

    ///將clientfd設(shè)置為非阻塞方式
    int oldSocketFlag = fcntl(clientfd, F_GETFL, 0);
    int newSocketFlag = oldSocketFlag | O_NONBLOCK;
    if (fcntl(clientfd, F_SETFL,  newSocketFlag) == -1)
    {
        close(clientfd);
        std::cout << "set socket to nonblock error." << std::endl;
        return -1;
    }

    //2.連接服務(wù)器
    struct sockaddr_in serveraddr;
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr(SERVER_ADDRESS);
    serveraddr.sin_port = htons(SERVER_PORT);
    for (;;)
    {
        int ret = connect(clientfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
        if (ret == 0)
        {
            std::cout << "connect to server successfully." << std::endl;
            close(clientfd);
            return 0;
        }
        else if (ret == -1)
        {
            if (errno == EINTR)
            {
                //connect 信號(hào)中斷了動(dòng)作,再次嘗試connect
                std::cout << "connecting interruptted by signal, try again." << std::endl;
                continue;
            }
            else if (errno == EINPROGRESS)
            {
                //正在嘗試連接
                break;
            }
            else
            {
                //的確出了問(wèn)題,
                close(clientfd);
                return -1;
            }
        }
    }

    fd_set writeset;
    FD_ZERO(&writeset);
    FD_SET(clientfd, &writeset);
    struct timeval tv;
    tv.tv_sec = 3;
    tv.tv_usec = 0;
    使用select函數(shù)來(lái)判斷socket是否可以寫(xiě)作。
    if (select(clientfd   1, NULL, &writeset, NULL, &tv) != 1)
    {
        std::cout << "[select] connect to server error." << std::endl;
        close(clientfd);
        return -1;
    }

    int err;
    socklen_t len = static_cast(sizeof err);
    //4.調(diào)用getsockopt檢查此時(shí)socket是否有錯(cuò)誤?
    if (::getsockopt(clientfd, SOL_SOCKET, SO_ERROR, &err, &len) < 0)
    {
        close(clientfd);
        return -1;
    }

    if (err == 0)
        std::cout << "connect to server successfully." << std::endl;
    else
        std::cout << "connect to server error." << std::endl;

    close(clientfd);

    return 0;
}

基本流程的TCP網(wǎng)絡(luò)編程


Linux和C 11多線(xiàn)程編程(學(xué)習(xí)筆記)


Linux select函數(shù)的用法和原理


socket的阻塞方式和非阻塞方式(send和recv函數(shù)在阻塞和非阻塞方式中的表現(xiàn))


在阻塞和非阻塞模式下,connect函數(shù)的行為


在接收緩沖區(qū)獲得相應(yīng)的socket可讀信息量。




本文僅代表作者觀點(diǎn),版權(quán)歸原創(chuàng)者所有,如需轉(zhuǎn)載請(qǐng)?jiān)谖闹凶⒚鱽?lái)源及作者名字。

免責(zé)聲明:本文系轉(zhuǎn)載編輯文章,僅作分享之用。如分享內(nèi)容、圖片侵犯到您的版權(quán)或非授權(quán)發(fā)布,請(qǐng)及時(shí)與我們聯(lián)系進(jìn)行審核處理或刪除,您可以發(fā)送材料至郵箱:service@tojoy.com