<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

    主站蜘蛛池模板: 久久成人国产精品免费软件| 亚洲国产成人精品无码久久久久久综合| 99视频有精品视频免费观看| 成人在线视频免费| 中文字幕亚洲综合久久男男| 国产成人精品亚洲2020| 99久久免费国产特黄| 成人啪精品视频免费网站| 亚洲一级在线观看| 国产羞羞的视频在线观看免费| 永久免费观看的毛片的网站| 老汉色老汉首页a亚洲| 中文字幕看片在线a免费| 国产精品99久久免费| 亚洲人成网站在线观看播放青青| 182tv免费视频在线观看| 亚洲av无码专区在线观看素人| 免费无码又爽又黄又刺激网站| 国产免费av片在线看| 亚洲视频网站在线观看| 久久久久久国产a免费观看不卡| 国产自产拍精品视频免费看| 黄人成a动漫片免费网站| 免费看的成人yellow视频| 免费夜色污私人影院网站| 亚洲国产另类久久久精品黑人 | 久久精品免费网站网| 亚洲天堂中文资源| 免费无码又爽又刺激网站| 亚洲综合色丁香麻豆| 成人免费区一区二区三区 | 亚洲最新中文字幕| 最近免费最新高清中文字幕韩国| 亚洲午夜久久久影院| 羞羞视频免费网站日本| 国产a级特黄的片子视频免费| 亚洲色大成网站WWW国产| 精品久久久久国产免费| 一个人看的www在线免费视频| 亚洲日韩国产一区二区三区| 无人视频免费观看免费视频|