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

yehao's Blog

套接字IO模型(一) Select模型

http://www.cnblogs.com/NeuqUstcIim/archive/2008/08/14/1268023.html
講一下套接字模式和套接字I/O模型的區別。先說明一下,只針對Winsock,如果你要骨頭里挑雞蛋把UNIX下的套接字概念來往這里套,那就不關我的事。
套接字模式阻塞套接字非阻塞套接字?;蛘呓型教捉幼趾彤惒教捉幼?。
套接字模型:描述如何對套接字的I/O行為進行管理。
Winsock提供的I/O模型一共有五種:

select,WSAAsyncSelect,WSAEventSelect,Overlapped,Completion。今天先講解select。

1:select模型擇模(選型)

先看一下下面的這句代碼:

阻塞socket

int iResult = recv(s, buffer,1024);

   這是用來接收數據的,在默認的阻塞模式下的套接字里,recv會阻塞在那里,直到套接字連接上有數據可讀,把數據讀到buffer里后recv函數才會返 回,不然就會一直阻塞在那里。

   在單線程的程序里出現這種情況會導致主線程(單線程程序里只有一個默認的主線程)被阻塞,這樣整個程序被鎖死在這里,如果永 遠沒數據發送過來,那么程序就會被永遠鎖死。這個問題可以用多線程解決,但是在有多個套接字連接的情況下,這不是一個好的選擇,擴展性很差。

非阻塞 socket:

再看代碼:
int iResult = ioctlsocket(s, FIOBIO, (unsigned long *)&ul);
iResult = recv(s, buffer,1024);

//-------------------------
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
  printf(
"Error at WSAStartup()\n");

//-------------------------
// Create a SOCKET object.
SOCKET m_socket;
m_socket 
= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_socket == INVALID_SOCKET) {
  printf(
"Error at socket(): %ld\n", WSAGetLastError());
  WSACleanup();
  
return;
}

//-------------------------
// Set the socket I/O mode: In this case FIONBIO
// enables or disables the blocking mode for the 
// socket based on the numerical value of iMode.
// If iMode = 0, blocking is enabled; 
// If iMode != 0, non-blocking mode is enabled.
int iMode = 0;
ioctlsocket(m_socket, FIONBIO, (u_long FAR
*&iMode);


這一次recv的調用不管套接字連接上有沒有數據可以接收都會馬上返回。原因就在于我們用ioctlsocket把套接字設置為非阻塞模式了。不過你跟蹤 一下就會發現,在沒有數據的情況下,recv確實是馬上返回了,但是也返回了一個錯誤:WSAEWOULDBLOCK,意思就是請求的操作沒有成功完成。 看到這里很多人可能會說,那么就重復調用recv并檢查返回值,直到成功為止,但是這樣做效率很成問題,開銷太大。

 

多線程來解決使用阻塞套接字存在的問題:

  多線程來解決阻塞套接字的方法是為阻塞套接字的IO操作創建單獨的線程,阻塞的套接字IO操作放在單獨的線程中,而不會因為套接字IO操作的阻塞造成整個主線程的阻塞,但是這樣也會造成一定的問題:

1) 如果是多個套接字的場合通過多線程來解決主線程阻塞就會顯得不合適了,server端創建一個監聽socket來負責監聽連接,而為accept函數

   為每個client端連接創建一個套接字,這樣就會創建很多的套接字。如果是創建不同的套接字則應該創建多個線程,而每個線程的線程函數是

   不同的,這樣就造成了所謂的擴展性很差。

2)如果不是每個連接創建一個套接字的話,duoxanch方法比較直觀,程序非常簡單而且可移植性好,但是不能利用平臺相關的特性。例如,如 果連接數增多的時候(成千上萬的連接),那么線程數成倍增長,操作 系統忙于頻繁的線程間切換,而且大部分線程在其生命周期內都是處于非活動狀態的,這大大浪費了系統的資源。所以,如果你已經知道你的代碼只會運行在 Windows平臺上,建議采用Winsock I/O模型。

 

微軟提供了select函數來解決這個問題

 int select(
int nfds,
fd_set FAR *readfds,
fd_set FAR *writefds,
fd_set FAR *exceptfds,
const struct timeval FAR *timeout
);

第一個參數不要管,會被系統忽略的。第二個參數是用來檢查套接字可讀性,也就說檢查套接字上是否有數據可讀,同樣,第三個參數用來檢查數據是否可以發出。最后一個是檢查是否有帶外數據可讀取。

 

 

最后一個參數是用來設置select等待多久的,是個結構:
struct timeval {
long tv_sec; // seconds
long tv_usec; // and microseconds
};
如果將這個結構設置為(0,0),那么select函數會馬上返回。

 說了這么久,select的作用到底是什么?

他的作用就是:

1)防止在在阻塞模式的套接字里被鎖死

2)避免在非阻塞套接字里重復檢查WSAEWOULDBLOCK錯誤。

 

他的工作流程如下:

1:用FD_ZERO宏來初始化我們感興趣的fd_set,也就是select函數的第二三四個參數。
2:用FD_SET宏來將套接字句柄分配給相應的fd_set。
3:調用select函數。
4:用FD_ISSET對套接字句柄進行檢查,如果我們所關注的那個套接字句柄仍然在開始分配的那個fd_set里,那么說明馬上可以進行相應的IO操 作。比如一個分配給select第一個參數的套接字句柄在select返回后仍然在select第一個參數的fd_set里,那么說明當前數據已經來了, 馬上可以讀取成功而不會被阻塞。

 

 1 #include "stdafx.h"
 2 #include <iostream>
 3 #include <winsock2.h>
 4 #include <windows.h>
 5 
 6 #define TRACE ATLTrace //必須要加上這個宏定義,否則在WIN32的控制臺程序中是不能直接用的
 7 
 8 #define InternetAddr "127.0.0.1"
 9 #define iPort 5055
10 
11 #pragma comment(lib, "ws2_32.lib")
12 
13 int _tmain(int argc, _TCHAR* argv[])
14 {
15     WSADATA wsa;
16     WORD wVersionRequested;
17     int err;
18 
19    wVersionRequested = MAKEWORD( 22 );
20     err = WSAStartup( wVersionRequested, &wsa);
21     if ( err != 0 ) {
22     //Tell the user that we could not find a usable 
23     //WinSock DLL.     
24     TRACE("你忘記添加WinSock DLL了\n");
25     WSACleanup();
26     return 1;
27      }
28 
29    // Create a SOCKET for listening for  incoming connection requests
30     SOCKET fdServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
31    
32     sockaddr_in server;
33 
34  server.sin_family = AF_INET;
35  server.sin_addr.s_addr = inet_addr(InternetAddr);
36  server.sin_port = htons(iPort);
37  //Bind the socket.
38     int ret = bind(fdServer, (sockaddr*)&server, sizeof(server));
39     ret = listen(fdServer, 4);
40 
41     SOCKET AcceptSocket;
42     fd_set     fdread;
43  timeval    tv;
44  int nSize;
45    //其實也算是輪訓,那么對阻塞socket用select和對使用非阻塞socket的優點在哪?
46   //可能的優點就是避免在非阻塞套接字里重復檢查WSAEWOULDBLOCK錯誤。
47     while(1)
48   {
49                  
50          FD_ZERO(&fdread);//初始化fd_set
51          FD_SET(fdServer, &fdread);//分配套接字句柄到相應的fd_set
52                              
53         tv.tv_sec = 2;//這里我們打算讓select等待兩秒后返回,避免被鎖死,也避免馬上返回
54         tv.tv_usec = 0;
55                                                  
56         select(0&fdread, NULL, NULL, &tv);
57                                                          
58         nSize = sizeof(server);
59         //先判斷fdServer是否還在fd_set內來判斷是否可以讀,這樣就避免因為 accept在等待
60         //時造成的阻塞
61         if (FD_ISSET(fdServer, &fdread))
62             //如果套接字句柄還在fd_set里,說明客戶端已經有connect的請求發過來了,
63             //馬上可以accept成功
64          {
65              AcceptSocket = accept(fdServer,( sockaddr*&server, &nSize);
66              break;
67            }                                             
68         else
69         //還沒有客戶端的connect請求,我們可以去做別的事,避免像沒有用select方式
70         //的阻塞套接字程序被鎖死的情況,如果沒用select,當程序運行到accept的時候客戶
71         //端恰好沒有connect請求,那么程序就會被鎖死,做不了任何事情
72             {
73             //do something
74                MessageBox(NULL, "waiting""recv", MB_ICONINFORMATION);
75         //別的事做完后,繼續去檢查是否有客戶端連接請求
76             }
77    }
78 
79    char buffer[128];
80       ZeroMemory(buffer, 128);
81 
82          ret = recv(AcceptSocket,buffer,128,0);//這里同樣可以用select,用法和上面一樣
83 
84          MessageBox(NULL, buffer, "recv", MB_ICONINFORMATION);
85 
86         closesocket(AcceptSocket);
87         WSACleanup();
88         return 0;
89 }
90 

 

select函數的返回值 :

函數失敗的返回值:調用失敗返回SOCKET_ERROR,超時返回0。

 

int ret;
        
if((ret=select(0,&fdread,NULL,NULL,NULL))==SOCKET_ERROR)
        {
            
//Error Condition
        }
        
if(ret > 0)//ret>0這個ret值表示滿足條件的socket的數量,不止一個socket滿足IO操作的條件
        {
            
if(FD_ISSET(fdServer,&fdread))
            {
                
//A read event has occured on socket fdServer
            }
        }

posted on 2011-08-18 16:11 厚積薄發 閱讀(503) 評論(0)  編輯 收藏 引用 所屬分類: 網絡編程

導航

<2025年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

統計

常用鏈接

留言簿

隨筆分類

文章分類

文章檔案

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产精品系列在线播放| 欧美亚洲视频在线观看| 亚洲午夜高清视频| 99精品国产一区二区青青牛奶| 悠悠资源网久久精品| 国产亚洲精品久久久久动| 国产精品一卡二卡| 韩国三级在线一区| 在线免费观看日韩欧美| 亚洲激情网站| 亚洲一区二区三区视频| 性欧美长视频| 欧美成人国产一区二区| 亚洲欧洲一区二区天堂久久| 亚洲欧洲视频| 亚洲欧美一区二区激情| 欧美一区二区三区播放老司机| 欧美一区二区三区视频免费播放| 欧美在线亚洲在线| 欧美国产在线视频| 国产欧美日韩视频在线观看| 1204国产成人精品视频| 99国产精品国产精品久久 | 韩国亚洲精品| 日韩视频在线一区| 性色一区二区| 亚洲国产成人不卡| 亚洲一区二区黄| 久久亚洲一区二区三区四区| 久久一综合视频| 欧美午夜大胆人体| 亚洲国产精彩中文乱码av在线播放| 亚洲精品视频一区| 欧美在线啊v一区| 亚洲高清不卡av| 欧美一级久久久| 欧美久色视频| 一区二区三区四区蜜桃| 你懂的视频欧美| 激情久久中文字幕| 午夜精品久久久久久久99水蜜桃 | 久久综合亚洲社区| 一区二区av在线| 欧美顶级大胆免费视频| 国产嫩草影院久久久久| 亚洲免费高清| 欧美高清在线一区| 欧美在线亚洲在线| 国产精品一区二区你懂的| 亚洲剧情一区二区| 欧美1级日本1级| 久久视频免费观看| 国产一区二区三区在线观看网站| 日韩一区二区免费高清| 美国十次成人| 久久米奇亚洲| 国产一区二区三区黄视频| 亚洲一级网站| 亚洲精品一二三| 欧美精品一区在线播放| 日韩视频在线观看免费| 亚洲高清网站| 欧美国产日韩精品| 一本色道久久88综合亚洲精品ⅰ| 亚洲第一黄色网| 欧美 日韩 国产在线| 亚洲日韩成人| 99视频热这里只有精品免费| 欧美精品在线免费播放| 一本综合精品| 亚洲一区二区三区成人在线视频精品| 欧美日韩一区二区三区在线视频 | 欧美激情一区二区三区在线视频 | 亚洲精品国精品久久99热一| 欧美国产日产韩国视频| 蜜桃久久av一区| 99在线|亚洲一区二区| 亚洲裸体俱乐部裸体舞表演av| 欧美日韩综合视频| 亚洲欧美国产77777| 亚洲一区在线观看免费观看电影高清 | 亚洲国产经典视频| 欧美另类一区| 欧美在线1区| 女人色偷偷aa久久天堂| 在线视频欧美日韩精品| 亚洲欧美在线免费观看| 在线观看欧美日韩| 99精品欧美一区二区三区| 亚洲女女做受ⅹxx高潮| 国产综合网站| 亚洲福利视频一区二区| 欧美日韩中文精品| 久久久国产午夜精品| 欧美高清不卡在线| 香蕉尹人综合在线观看| 久久久一二三| 亚洲欧美国产制服动漫| 欧美一区日韩一区| 9色精品在线| 久久久国产午夜精品| 亚洲图片欧洲图片av| 久久久视频精品| 亚洲欧美激情视频| 猛男gaygay欧美视频| 午夜精品久久久久久久久久久| 老司机亚洲精品| 欧美中文字幕视频| 欧美日韩国产丝袜另类| 美女主播精品视频一二三四| 国产精品v欧美精品v日韩精品| 欧美成人自拍视频| 国产网站欧美日韩免费精品在线观看| 最新成人在线| 尤物九九久久国产精品的特点| 中日韩在线视频| 日韩午夜av电影| 久久一区二区三区超碰国产精品| 亚洲欧美三级在线| 欧美人牲a欧美精品| 蜜桃精品久久久久久久免费影院| 国产精品区免费视频| 亚洲最新视频在线| 日韩亚洲欧美一区| 欧美成人免费全部| 欧美成人免费在线观看| 禁断一区二区三区在线| 亚洲欧美中文日韩v在线观看| 在线视频欧美精品| 欧美日韩 国产精品| 亚洲国产精品国自产拍av秋霞| 伊人久久亚洲美女图片| 久久国产精品免费一区| 久久久国际精品| 黄色成人精品网站| 久久久精品动漫| 欧美成人综合网站| 亚洲人成在线播放网站岛国| 免费不卡亚洲欧美| 亚洲国产日日夜夜| 在线视频日本亚洲性| 欧美日韩在线观看一区二区三区 | 亚洲精品乱码| 一区二区三区视频在线观看| 欧美精品三级在线观看| 亚洲欧洲日本专区| 亚洲一区在线观看视频 | 国产精品成人一区二区三区吃奶 | 久久久久久噜噜噜久久久精品| 久久久久免费视频| 美玉足脚交一区二区三区图片| 欧美电影资源| 99视频精品在线| 国产精品久久亚洲7777| 亚洲宅男天堂在线观看无病毒| 午夜精品久久久久| 国内精品一区二区| 欧美国产乱视频| 亚洲伊人观看| 久久一区中文字幕| 亚洲欧洲一区二区在线观看| 欧美日韩视频在线一区二区| 亚洲深夜福利网站| 六月婷婷久久| 亚洲天堂成人在线观看| 国产欧美一区二区三区国产幕精品 | 毛片一区二区| 国产精品99久久99久久久二8| 国产精品户外野外| 久久亚洲捆绑美女| 在线性视频日韩欧美| 久久综合综合久久综合| 亚洲免费观看| 国产有码在线一区二区视频| 欧美高清视频| 久久不射网站| 艳女tv在线观看国产一区| 久久久亚洲高清| 在线视频中文亚洲| 在线精品国精品国产尤物884a| 欧美午夜片欧美片在线观看| 久久久久久69| 亚洲中午字幕| 亚洲精品乱码| 欧美+日本+国产+在线a∨观看| 亚洲视频免费在线观看| 伊人久久大香线| 国产欧美欧洲在线观看| 欧美精品激情blacked18| 欧美亚洲在线播放| 国产精品99久久久久久久女警| 欧美成人国产va精品日本一级| 亚洲欧洲99久久| 一区二区三区精品久久久| 伊人影院久久| 国产在线视频欧美一区二区三区| 欧美三区视频| 欧美破处大片在线视频| 欧美sm重口味系列视频在线观看| 欧美亚洲免费电影|