青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

kenlistian

厚積薄發(fā). 勤為槳,思為帆

   :: 首頁 :: 新隨筆 ::  :: 聚合  :: 管理 ::
  73 隨筆 :: 4 文章 :: 22 評論 :: 0 Trackbacks

未命名

在其中,要注意的是:

  1.關于服務端在客戶端連接之前

      如果沒有客戶端連接時,在調用accept()時程序將會出現(xiàn)freeze,即阻塞,而一旦有客戶端連接過來,accept將會新建一Socket與客戶端的Socket相通,原先Socket繼續(xù)進入監(jiān)聽狀態(tài),等待他人的連接要求。
     該函數(shù)調用成功返回一個新產(chǎn)生的Socket對象,否則返回INVALID_SOCKET,該新socket就是一個和一個客戶端對話的套接字。有點類似孫悟空對陣天兵天將時,當遇到某個具體敵手來,拔出一根毫毛變出一個孫行者去應付,再來再拔毫毛一樣。accept()定義如下:
SOCKET PASCAL FAR accept( SCOKET s, struct sockaddr FAR *addr,int FAR *addrlen );
s:Socket的識別碼;
addr:存放來連接的客戶端的地址;
addrlen:addr的長度

  當客戶端連接上后一直沒有斷開情況下,如果連接越來越多時,則創(chuàng)建的Socket也越多,其最大上限在listen中已經(jīng)設置。

2.關于服務端的accept()使用

  accept過后才是真正的和客戶端進行交互,在accept時,由于程序會freeze,在調用accept時有多種方法,其中方法有:

*事件處理模式:

     通過WSAAsyncSelect()函數(shù),其異步通知有accept信號來,然后在一個窗體自定義事件中處理accept信號。   

   如下在listen()之后調用:

        WSAAsyncSelect(m_hSocket, m_hWnd, WM_CLIENT_ACCEPT,FD_ACCEPT);  //wm_xxx_xxz自定義消息。

  這樣在構建的自定義消息中處理accept()連接請求。如下,OnAccept()單元

       LRESULT CPublicNetSoftDlg::OnAccept(WPARAM wParam,LPARAM lParam)
       {

             。。。。
               if(WSAGETSELECTEVENT(lParam) == FD_ACCEPT)//如果
                {
                         Client = accept(ServerSocket,(LPSOCKADDR)&m_sockServerAddr,0);

                        if (Client == INVALID_SOCKET) 
                            return 0L;
                }

            。。。。。
    }

*線程處理模式:將accept放在線程中讓其freeze,一旦來了連接,則自然從freeze中出來進行處理下一步。下面就是直接把accetp放在線程中處于等待狀態(tài)。

//連接請求隊列長度為1,即只允許有一個請求,若有多個請求, 則出現(xiàn)錯誤,給出錯誤代碼WSAECONNREFUSED。
listen(sock,1);
//開啟線程避免主程序的阻塞
AfxBeginThread(Server,NULL);
……

//處理線程,等待客戶端連接
UINT Server(LPVOID lpVoid)
{
……
   int nLen = sizeof(SOCKADDR);
   connSocket = accept(ListSocket,(LPSOCKADDR)& sockin,(LPINT)& nLen);
   ……
    WSAAsyncSelect(connSocket,
                 m_hWnd,
                 WM_SOCKET_MSG,
                 FD_READ|FD_CLOSE);
    return 1;
}
  把accept()放到線程中去是因為在執(zhí)行到該函數(shù)時如沒有客戶連接請求到來,服務器就會停在accept語句上處于等待阻塞,這勢必會引起進程的阻塞,雖然也可以通過設置套接字為非阻塞方式使在沒有客戶等待時可以使accept()函數(shù)調用立即返回,但這種輪詢套接字的方式會使CPU處于忙等待方式,從而降低程序的運行效率大大浪費系統(tǒng)資源(我覺得做法很多,暫不考慮非阻塞情況)。
      在阻塞工作方式,為其單獨開辟一個子線程,將其阻塞控制在子線程范圍內(nèi)而不會造成整個應用程序的阻塞。對于網(wǎng)絡事件的響應顯然要采取異步選擇機制,只有采取這種方式才可以在由網(wǎng)絡對方所引起的不可預知的網(wǎng)絡事件發(fā)生時能馬上在進程中做出及時的響應處理,而在沒有網(wǎng)絡事件到達時則可以處理其他事件,這種效率是很高的。前面那段代碼中的WSAAsyncSelect()函數(shù)便是實現(xiàn)網(wǎng)絡事件異步選擇的核心函數(shù)。
    第4個參數(shù)注冊應用程序關心的網(wǎng)絡事件,在這里通過FD_READ|FD_CLOSE指定了網(wǎng)絡讀和網(wǎng)絡斷開兩種事件,當這種事件發(fā)生時變會發(fā)出由第三個參數(shù)指定的自定義消息 WM_SOCKET_MSG,接收該消息的窗口通過第二個參數(shù)指定其句柄。

其響應函數(shù)如下:

void CNetServerView::OnSocket(WPARAM wParam,LPARAM lParam)
{
    int iReadLen=0;
   int message=lParam & 0x0000FFFF;
   switch(message)
   {
     case FD_READ:     //讀事件發(fā)生。此時有字符到達,需要進行接收處理
        char cDataBuffer[MTU*10];
        //通過套接字接收信息
        iReadLen = recv(newskt,cDataBuffer,MTU*10,0);
       //將信息保存到文件
        if(!file.Open("ServerFile.txt",CFile::modeReadWrite))
             file.Open("E:ServerFile.txt",
                 CFile::modeCreate|CFile::modeReadWrite);
         file.SeekToEnd();
         file.Write(cDataBuffer,iReadLen);
         file.Close();
         break;
         case FD_CLOSE://網(wǎng)絡斷開事件發(fā)生。此時客戶機關閉或退出。
             ……//進行相應的處理
                break;
         default:
               break;
      }
}

   對于recv和send的處理一般就是在事件中處理,通過WSAAsySelect()來傳遞信號,這種方式形成一種固定寫socket方式,比如有的人喜歡把recv和send各自放入一個線程中通過輪詢+阻塞模式,或者采用事件通知模式,一般來說采用I/O模型是較為專業(yè)的做法。

3.客戶端的connect()

    客戶端連接時存在阻塞現(xiàn)象,就是程序在connect會出現(xiàn)freeze,一般可以容忍。但若想通過超時設置來解決這個問題,可采用在vckbase中,對于connect()超時的處理辦法。不過覺得有時調用封裝好的socket,直接是指connectionTimeout屬性倒是簡單的方法。

WSADATA wsd;
SOCKET cClient;
int ret;
struct sockaddr_in server;
hostent *host=NULL;

if(WSAStartup(MAKEWORD(2,0),&wsd))

{

   return 0;

}
cClient = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(cClient == INVALID_SOCKET){return 0;}
//set Recv and Send time out
int TimeOut=6000; //設置發(fā)送超時6秒
if(::setsockopt(cClient,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){
     return 0;
}
TimeOut = 6000;//設置接收超時6秒
if(::setsockopt(cClient,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){
return 0;
}
//設置非阻塞方式連接
unsigned long ul = 1;
ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul);
if(ret==SOCKET_ERROR)  return 0;

//連接
server.sin_family = AF_INET;
server.sin_port = htons(25);
server.sin_addr .s_addr = inet_addr((LPCSTR)pSmtp);
if(server.sin_addr.s_addr == INADDR_NONE){return 0;}

//運行這里將不會阻塞,而是直接運行下去,通過select中設置的 timeval結構參數(shù)設定連接超時處理。

connect(cClient,(const struct sockaddr *)&server,sizeof(server));

//select 模型,即設置超時
struct timeval timeout ;
fd_set r;

FD_ZERO(&r);
FD_SET(cClient, &r);
timeout.tv_sec = 15; //連接超時15秒
timeout.tv_usec =0;
ret = select(0, 0, &r, 0, &timeout);            //超時socket將關閉
if ( ret <= 0 )
{
         ::closesocket(cClient);
          return 0;
}
//一般非鎖定模式套接比較難控制,可以根據(jù)實際情況考慮 再設回阻塞模式,又把狀態(tài)設置為 阻塞狀態(tài)。
unsigned long ul1= 0 ;
ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul1);
if(ret==SOCKET_ERROR){
         ::closesocket (cClient);
          return 0;
}

 

4.select()

a. 當你希望服務器監(jiān)聽連接服務請求,而又不想通過輪詢的方式,則理想的方式是調用select().它運行你把程序本身掛起來,而同時使系統(tǒng)內(nèi)核監(jiān)聽所要求的一組文件描述符的任何活動,只要確認在任何被監(jiān)控的文件描述符上出現(xiàn)了活動,select()調用將返回指示該文件描述符已準備好的信息,從而實現(xiàn)了程序的選出是隨機變化的,而不必由程序本身對輸入進行測試而浪費cpu開銷,

    在socket編程中,select函數(shù)一般在非阻塞的socket中,用來檢查socket緩沖區(qū)中是否有數(shù)據(jù)可讀,或是否可以寫數(shù)據(jù)到socket緩沖區(qū)。  
  有時,select()也被用來當作延時函數(shù)使用。sleep()延時會釋放cpu,用select的話,可以在占用cpu的情況下,延時。

   select()是用來進行多路轉接的函數(shù)。它可以同時等待n(n大于等于1)個文件描述字或者socket套接口。只要它等待的任意描述字準備好或者等待時間超過了設定時間程序就往下執(zhí)行。可以防止進程長時間阻塞,占用資源。

b.簡單說法:

  如果你要發(fā)數(shù)據(jù)用select(sock+1,&s,NULL,NULL,NULL);  
     if(FD_ISSET(sock,&s)   ,你可以發(fā)了。send   it  
  如果你要收數(shù)據(jù)用select(sock+1,NULL,&s,NULL,NULL);  
  if(FD_ISSET(sock,&s)   ,你可以收了。recv   it  

socket默認情況下是阻塞的,除非你用WSAAsyncSelect   OR   select   就變成NOBBLOCKING,  
  將阻塞設為非阻塞如下:  
  int   opt=1;  
  ioctlsocket(sock,FIONBIO,&opt)  
  若opt=0就是阻塞的了

 

c.用法一

  fd_set m_readfds;  
  fd_set m_exceptfds;  
  timeval m_tmOut;  
  m_tmOut.tv_sec =   120;     //接收時間如果超過120秒,即認為網(wǎng)絡連接已經(jīng)中斷,  
  m_tmOut.tv_usec =   0;      //客戶端應該定時每40秒發(fā)送一次空閑信號,以防止被誤認為是網(wǎng)絡連接中斷。  
  FD_ZERO(   &m_readfds   );  
  FD_ZERO(   &m_exceptfds   );  
  FD_SET(   m_scSocket,   &m_exceptfds   );  
  FD_SET(   m_scSocket,   &m_readfds   );  
  int CNet::Receive(   char   *   szBuff,   int   iSize   )  
  {  
        int   iRet;  
        if(   m_ntType   ==   _NET_SERVER_   )  
        {  
              iRet   =   select(   m_scSocket   +   1,   &m_readfds,   NULL,   &m_exceptfds,   &m_tmOut   );  
              if(   iRet   ==   0   )  
             {  
                   m_iError =   13; //超時  
                   return   -2;  
             }  
             if(   iRet   ==   SOCKET_ERROR   )  
            {  
                 GetLastError(   );  
                  return   -1;  
            }  
            if(   FD_ISSET(   m_scSocket,   &m_exceptfds   )   )  
            {  
                  m_iError =   14; //連接被終止  
                  return   -1;  
           }  
      }  
      iRet   =   recv(   m_scSocket,   szBuff,   iSize,   0   );  
      if(   iRet   ==   0   )  
     {  
               m_iError =   14; //連接被終止  
              return   -1;  
    }  
   if(   iRet   ==   SOCKET_ERROR   )  
   {  
          GetLastError(   );  
          return   -1;  
   }  
    return   iRet;  
  }  

用法二

int   recvex_sock(SOCKET   sock,   void*   buf,   int   len,   int   sec)  
  {  
                  int   rs;  
                  fd_set   fd;  
                  struct   timeval   tv;  
                  memset(&tv,   0,   sizeof(tv));  
                  if   (   sec   >   0   )  
                                  tv.tv_sec   =   sec;  
                  FD_ZERO(&fd);  
                  FD_SET(sock,   &fd);  
                  rs   =   select(sock   +   1,   &fd,   0,   0,   sec   >=   0   ?   &tv   :   NULL);  
                  if   (   rs   ==   0   )  
                                  return   SOCKET_TIMEOUT;  
                  if   (   rs   <   0   )  
                                  return   SOCKET_ERROR;  
                  if   (   !FD_ISSET(sock,   &fd)   )  
                                  return   SOCKET_ERROR;  
                  return   (recv_sock(sock,   buf,   len));  
  } 

posted on 2007-12-06 14:21 kenlistian 閱讀(3060) 評論(0)  編輯 收藏 引用
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品午夜视频| 在线精品视频在线观看高清 | 国产午夜精品一区理论片飘花| 国产伦理一区| 亚洲一区日本| 亚洲人成人一区二区在线观看| 亚洲精品美女| 欧美激情亚洲另类| 亚洲高清网站| 欧美国产日韩一区二区| 久久激情综合| 国产一区二区黄| 欧美一区二区国产| 亚洲一区二三| 国产日韩精品一区二区三区| 一区二区三区黄色| 日韩视频免费观看| 国产精品www网站| 一区二区三区四区五区精品| 亚洲人成艺术| 国产精品扒开腿做爽爽爽视频 | 夜夜精品视频一区二区| 欧美日韩国产成人在线91| 亚洲最新中文字幕| 一区二区免费在线观看| 国产精品人人做人人爽人人添| 亚洲欧美激情视频| 在线欧美三区| 亚洲国产精品一区二区尤物区| 欧美二区在线看| 在线午夜精品自拍| 亚洲在线观看免费| 一区二区在线观看视频| 亚洲成在人线av| 欧美色欧美亚洲高清在线视频| 亚洲在线视频免费观看| 欧美一区二区三区播放老司机 | 国产婷婷精品| 久久综合中文色婷婷| 免费观看成人| 亚洲欧美日韩人成在线播放| 欧美在线视频在线播放完整版免费观看 | 欧美国产免费| 欧美视频免费看| 久久精品亚洲一区二区| 久久综合色8888| 亚洲在线成人精品| 久久久www成人免费精品| 99re热精品| 久久9热精品视频| 日韩视频一区二区| 欧美一级淫片播放口| 日韩视频一区二区三区| 午夜精品美女久久久久av福利| 91久久精品网| 性欧美大战久久久久久久免费观看| 亚洲国产成人av| 午夜精品一区二区三区在线视| 亚洲激情一区| 欧美一区在线视频| 亚洲图片你懂的| 久久综合伊人77777蜜臀| 午夜精品久久久| 欧美精品一区二区三区高清aⅴ| 久久精品一二三| 国产精品久久久久aaaa樱花| 欧美刺激午夜性久久久久久久| 国产精品www网站| 亚洲日本理论电影| 亚洲国产高清自拍| 久久精品99| 欧美在线观看视频| 国产精品v日韩精品v欧美精品网站 | 美女视频黄a大片欧美| 国产精品久久久久久福利一牛影视| 嫩模写真一区二区三区三州| 国产精品无码永久免费888| 亚洲精品免费一区二区三区| 亚洲激情欧美| 久久深夜福利| 久久夜色精品国产欧美乱| 国产精品一区二区男女羞羞无遮挡 | 亚洲视频观看| 蜜桃精品久久久久久久免费影院| 亚欧成人在线| 国产精品乱码人人做人人爱| 91久久久久| 亚洲精品护士| 欧美高清你懂得| 亚洲国产一成人久久精品| 亚洲国产综合在线| 欧美高清视频一区二区| 亚洲国产精品久久精品怡红院| 亚洲高清精品中出| 蜜臀91精品一区二区三区| 欧美福利视频网站| 亚洲欧洲一级| 欧美国产成人精品| 亚洲精品小视频| 亚洲综合日韩中文字幕v在线| 欧美激情久久久久| 亚洲精品视频在线播放| 亚洲午夜视频| 国产精品欧美日韩| 欧美中文在线字幕| 欧美成在线视频| 一区二区三区视频免费在线观看| 欧美日韩性生活视频| 亚洲一区二区影院| 久久影院午夜片一区| 亚洲国产小视频在线观看| 欧美精品国产精品| 亚洲主播在线观看| 麻豆av一区二区三区久久| 亚洲精品久久久久久久久久久 | 在线国产亚洲欧美| 欧美成人在线网站| 一二三四社区欧美黄| 欧美亚洲视频在线观看| 在线观看av一区| 欧美日韩在线观看一区二区三区| 亚洲午夜精品在线| 美女主播一区| 亚洲一区二区三区高清不卡| 国产日韩一区在线| 欧美福利专区| 欧美在线综合视频| 亚洲精品免费在线| 久久视频在线看| 中文在线资源观看网站视频免费不卡 | 久久久噜久噜久久综合| 亚洲精品久久嫩草网站秘色| 午夜精品久久久久久久久久久久久 | 亚洲精选一区| 久久久久五月天| av成人天堂| 狠狠干综合网| 国产精品jvid在线观看蜜臀| 久久久视频精品| 亚洲一级高清| 亚洲高清视频一区二区| 欧美一区二区三区另类| 99国产精品久久久久久久| 国产无遮挡一区二区三区毛片日本| 欧美gay视频| 久久久不卡网国产精品一区| 亚洲欧洲一区二区三区在线观看 | 国产欧美在线观看| 欧美日韩成人在线视频| 久久久久九九九| 亚洲性视频网站| 亚洲日本成人在线观看| 老司机aⅴ在线精品导航| 午夜视频在线观看一区| 亚洲国产另类久久精品| 国产婷婷精品| 国产精品一二三四| 国产精品mm| 欧美日韩免费精品| 欧美丰满高潮xxxx喷水动漫| 久久婷婷亚洲| 久久精品亚洲一区二区| 午夜影视日本亚洲欧洲精品| 亚洲精品三级| 亚洲国产精品免费| 欧美黄色一区二区| 欧美成人中文| 欧美激情a∨在线视频播放| 久久久久久久综合日本| 欧美一区二区三区视频免费| 亚洲一品av免费观看| 夜夜精品视频一区二区| 99国产精品私拍| 一本大道av伊人久久综合| 亚洲国产高清aⅴ视频| 在线日韩中文| 亚洲国产精品尤物yw在线观看| 黄色成人在线| 在线观看日产精品| 亚洲国产黄色| 亚洲黄网站黄| 夜夜精品视频| 亚洲综合色在线| 欧美在线视频免费播放| 久久精品72免费观看| 久久久久久免费| 欧美韩日视频| 亚洲精品视频免费在线观看| 亚洲美女免费精品视频在线观看| 怡红院精品视频| 亚洲福利在线观看| 亚洲精品久久久蜜桃| 一区二区日韩伦理片| 亚洲一区二区三区在线观看视频| 亚洲一区二区三区四区五区黄| 亚洲欧美另类中文字幕| 久久成人精品视频| 欧美大片在线观看一区二区| 91久久精品国产91久久| 亚洲视频在线一区观看|