<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    海闊天空

    I'm on my way!
    隨筆 - 17, 文章 - 69, 評論 - 21, 引用 - 0
    數據加載中……

    socket編程


    今天只想談一談關于阻塞和非阻塞的socket。

    調用socket函數得到的socket的文件標示符,默認情況下是一個阻塞的socket,從應用角度,就是每當調用accept,recv,send 等函數的時候,如果對方沒有相應,那么進程會阻塞在那里,直到對方相應。這在應用中有很多不便,尤其是在windows環境中的編程,如果進程被阻塞那么 看上去有一點像死機的感覺。

    其實把一個socket設置為非阻塞的也很簡單。但是,應用select函數,阻塞socket也可以到達類似的效果。一會詳細討論。

    先考慮一個TCP的連接,當服務器程序listen以后,如果直接調用accept,那么進程會阻塞在那里,一直到被client端connect,然后 開啟一個新的線程處理客戶的服務,主線程繼續監聽請求。這樣可以實現同時處理多個客戶端連接,但是這樣是會阻塞主線程,不是一個好的辦法。其實,我當然也 可添加一個線程,在“后臺”accept,但是我覺得這里面有一個多線程操作同一個文件描述符socket的問題。也不是很好。也就是說,如果只用到線程 機制,并不能很好的解決阻塞的問題。

    select函數可以對一套文件描述符操作(windows里叫handle,我覺得沒有什么本 質的區別。都是進程空間里面的一個整數而已),觀察這套文件描述符的可讀或可寫的情況。這樣就給我們提供這樣一個思路,只有當一個socket是可讀的, 也就是有遠程連接請求connect或是對套接口write,那么才去調用accept或是read,這樣就可以避免阻塞了。

    以準備accept的套接口為例,如果調用socket函數得到的文件描述符為s=3,那么,我可以調用select監視所有4以下的文件描述符的讀寫特 性。 select(s+1,&fd_readset,&fd_writeset,&fd_errorset,&tv_time). 這個函數是內核等待特定事件的函數,并不是只有套接口可以用。原型是

    int select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval *timeout);

    第一個參數表示觀察的最大的文件描述符,一般是你想要觀察的socket+1, 第二個參數是可讀文件描述符set,第三個是可寫set,第四個參數是error set,第五個是超時的時間。如果在超時的時間內沒有觀察過任何改動,那么函數會清空這幾個set(我個人理解),并且返回0;如果出錯,會返回-1。否 則返回>0,并且只把可讀(可寫)的文件描述符保留在對應的set內。所以只要在調用select以前,把等待連接的套接口放到可讀set中,如果 發生connect,select會返回>0,這時候可以觀察一下套接口是否還在這個set中,如果是,則說明有請求。這個方法可以用于多個套接口 同時監聽多個端口的情況。也可以用于一個已經連接的套接口等待對方發送的消息,比如write。

    對于set的操作,有如下幾個宏:FD_ZERO,FD_SET,FD_ISSET,FD_CLR.

    fd_set myset; //定義描述字集數據類型

    FD_ZERO (&myset); //對描述字集初始化

    FD_SET(s, &myset); //打開描述字的第s位,也即把套接口加入set中

    FD_ISSET(s, &myest) //測試描述字的第s位,這個宏一般是在select之后才會用到。

    FD_CLR(s, &myset) // //關閉描述字的第s位,就是在set中清除s.

    這個函數的使用方法,可以參見下面的程序。就不再細訴了。

    FD_ZERO(&fs_ReadSet);
    FD_SET(iSockets, &fs_ReadSet);
    iSockNum = iSockets+1;

    while(1)
    {
    FD_ZERO(&fs_WriteSet);
    for (iSocketz = 0; iSocketz<iSockNum; iSocketz++)
    {
    if (FD_ISSET(iSocketz, &fs_ReadSet))
    FD_SET(iSocketz, &fs_WriteSet);
    }

    tv_time.tv_sec = 2;
    tv_time.tv_usec = 500000;
    iRtn = select(iSockNum, &fs_WriteSet, NULL, NULL, &tv_time);
    if (iRtn == -1)
    {
    printf("function select error\n");
    goto error;
    }
    else if(iRtn == 0)
    {
    continue;
    }

    if (FD_ISSET(iSockets, &fs_WriteSet))
    {
    iSockLen = sizeof(sa_client);
    iSocketz = accept(iSockets, (struct sockaddr*)&sa_client, &iSockLen);
    if (iSocketz == -1)
    {
    printf("function accept error \n");
    goto error;
    }
    printf("z : %d\n", iSocketz);

    if (iSocketz >=MAX_CLIENT)
    {
    close(iSocketz);
    continue;
    }
    if (iSockNum < iSocketz+1)
    iSockNum = iSocketz+1;
    FD_SET(iSocketz, &fs_ReadSet);

    }

    for (iSocketz=iSockets+1; iSocketz < iSockNum; iSocketz++)
    {

    if (FD_ISSET(iSocketz, &fs_WriteSet))
    {
    memset(pRcvBuf, 0, BUFFERSIZE);
    memset(pSndBuf, 0, BUFFERSIZE);
    iRtn = read(iSocketz, pRcvBuf, BUFFERSIZE);
    if (iRtn == -1)
    {
    printf("function read error \n");
    goto error;
    }

    printf("%s\n", pRcvBuf);

    pSndBuf[0] = 0;
    strcpy(pSndBuf, "fuck");
    iBufLen = sizeof("fuck");

    iRtn = write(iSocketz, pSndBuf, iBufLen);
    if (iRtn == -1)
    {
    printf("function write error \n");
    goto error;
    }

    if(strcmp(pRcvBuf,"exit")==0)
    {
    FD_CLR(iSocketz, &fs_ReadSet);
    close(iSocketz);
    }
    }

    }
    for (iSocketz = iSockNum-1; (iSocketz >iSockets&&!FD_ISSET(iSocketz, &fs_ReadSet)); iSocketz = iSockNum-1)
    {
    iSockNum = iSocketz;
    }
    //printf("isockNum: %d\n",iSockNum);
    }

    至于套接口的通信,我還想說一點,套接口和文件管道差不多,一方讀一方寫,read會阻塞到對方write,而write不會阻塞。應該是這樣了。如果我個人對這個部分的理解有錯誤。會在以后改正。

    posted on 2009-12-14 11:35 石頭@ 閱讀(471) 評論(0)  編輯  收藏 所屬分類: Tcp/Ip

    主站蜘蛛池模板: 日本高清色本免费现在观看| 久久夜色精品国产嚕嚕亚洲av| 国内自产拍自a免费毛片| 免费人成在线观看网站品爱网日本 | 亚洲导航深夜福利| 日本激情猛烈在线看免费观看| 你懂的免费在线观看网站| 免费人成在线观看网站视频 | 女人被男人躁的女爽免费视频| 亚洲人成小说网站色| 国产好大好硬好爽免费不卡| 亚洲AV中文无码字幕色三| 老司机午夜在线视频免费| 国产va免费精品观看精品| 久久久亚洲精品无码| 91福利免费体验区观看区| 国产亚洲AV夜间福利香蕉149 | 少妇性饥渴无码A区免费| 色www永久免费视频| 亚洲国产精品成人精品小说| 亚洲性线免费观看视频成熟| 亚洲国产一区二区a毛片| 国产99久久久国产精免费| 国产一精品一aⅴ一免费| 亚洲综合欧美色五月俺也去| 黄+色+性+人免费| 久久精品国产亚洲av麻豆小说 | 亚洲av无码片在线播放| 免费观看无遮挡www的视频| 亚洲国产高清人在线| 国产精品免费观看久久| 亚洲依依成人精品| 亚洲w码欧洲s码免费| 久久亚洲精品无码av| vvvv99日韩精品亚洲| 男人免费视频一区二区在线观看 | 亚洲免费一级视频| 亚洲午夜福利精品无码| 一级毛片免费在线播放| 亚洲无码日韩精品第一页| 9420免费高清在线视频|