异步SOCKET与同步SOCKET
阻塞與非阻塞SOCKET
Windows套接字在兩種模式下執行I/O操作,阻塞和非阻塞。在阻塞模式下,在I/O操作完成前,執行操作的Winsock函數會一直等待下去,不會立即返回程序(將控制權交還給程序)。而在非阻塞模式下,Winsock函數無論如何都會立即返回。
Windows Sockets的異步選擇函數WSAAsyncSelect()提供了消息機制的網絡事件選擇,當使用它登記的網絡事件發生時,Windows應用程序相應的窗口函數將收到一個消息,消息中指示了發生的網絡事件,以及與事件相關的一些信息。
在同步模式中,對執行網絡操作的函數(如Send和receive)的調用一直等到操作完成后才將控制權返回給調用程序;
在異步模式中,這些調用立即返回控制權
阻塞模式
當使用socket()函數創建套接字時,默認的套接字都是阻塞的。這意味著當調用Windows Sockets API不能立即完成時,線程處于等待狀態,直到操作完成。
1.輸入操作
recv()、recvfrom()、WSARecv()和WSARecvfrom()函數。以阻塞套接字為參數調用該函數接收數據。如果此時套接字緩沖區內沒有數據可讀,則調用線程在數據到來前一直睡眠。
2.輸出操作
send()、sendto()、WSASend()和WSASendto()函數。以阻塞套接字為參數調用該函數發送數據。如果套接字緩沖區沒有可用空間,線程會一直睡眠,直到有空間。
3.接受連接
accept()和WSAAcept()函數。以阻塞套接字為參數調用該函數,等待接受對方的連接請求。如果此時沒有連接請求,線程就會進入睡眠狀態。
4.外出連接
connect()和WSAConnect()函數。對于TCP連接,客戶端以阻塞套接字為參數,調用該函數向服務器發起連接。該函數在收到服務器的應答前,不會返回。這意味著TCP連接總會等待至少到服務器的一次往返時間。
使用阻塞模式的套接字,開發網絡程序比較簡單,容易實現。當希望能夠立即發送和接收數據,且處理的套接字數量比較少的情況下,使用阻塞模式來開發網絡程序比較合適。
非阻塞模式
?????把套接字設置為非阻塞模式,即通知系統內核:在調用Windows Sockets API時,不要讓線程睡眠,而應該讓函數立即返回。
當使用socket()函數和WSASocket()函數創建套接字時,默認都是阻塞的。在創建套接字之后,通過調用ioctlsocket()函數,將該套接字設置為非阻塞模式。還可以使用WSAAsyncselect()和WSAEventselect()函數。當調用該函數時,套接字會自動地設置為非阻塞方式。
套接字設置為非阻塞模式后,在調用Windows Sockets API函數時,調用函數會立即返回。大多數情況下,這些函數調用都會調用“失敗”,并返回WSAEWOULDBLOCK錯誤代碼。說明請求的操作在調用期間內沒有時間完成。通常,應用程序需要重復調用該函數,直到獲得成功返回代碼。(bind, WSAStartup ?不會返回該錯誤)
由于使用非阻塞套接字在調用函數時,會經常返回WSAEWOULDBLOCK錯誤。所以在任何時候,都應仔細檢查返回代碼并作好對“失敗”的準備。應用程序連續不斷地調用這個函數,直到它返回成功指示為止。上面的程序清單中,在While循環體內不斷地調用recv()函數,以讀入1024個字節的數據。這種做法很浪費系統資源。
要完成這樣的操作,有人使用MSG_PEEK標志調用recv()函數查看緩沖區中是否有數據可讀。同樣,這種方法也不好。因為該做法對系統造成的開銷是很大的,并且應用程序至少要調用recv()函數兩次,才能實際地讀入數據。較好的做法是,使用套接字的“I/O模型”來判斷非阻塞套接字是否可讀可寫。
非阻塞模式套接字 vs 阻塞模式套接字
1.?使用非阻塞模式套接字,需要編寫更多的代碼,以便在每個Windows Sockets API函數調用中,對收到WSAEWOULDBLOCK錯誤進行處理。因此,非阻塞套接字便顯得有些難于使用。
2.?非阻塞套接字在控制建立的多個連接,在數據的收發量不均,時間不定時,明顯具有優勢。
通常情況下,可考慮使用套接字的“I/O模型”,它有助于應用程序通過異步方式,同時對一個或多個套接字的通信加以管理。
MFC CAsynSocket
MFC 定義了兩個套接字類:CAsyncSocket、CSocket;CSocket派生于CAsyncSocket;
CAsyncSocket類在低層次上對 Windows Sockets API 進行了封裝,其成員函數和 Windows Sockets API 函數直接相對應 。
一個CAsyncSocket對 象 就 代 表 了一 個 套 接 字。
而CSocket繼承于CAsyncSocket 類,是對 Windows Sockets API 的高級封裝。
一 客戶端程序:
1. 創建一個Dialog Based項目:CSockClient
2. 設計對話框
去掉Ok和Cancle兩個按鈕,增加ID_Connect(連接)、ID_Send(發送)、ID_Exit(關閉)按鈕,增加ListBox控件IDC_LISTMSG和Edit控件IDC_EDITMSG,并按下表在ClassWizard中為CCSockClientDlg類添加變量。
IDC_EDITMSG CEdit m_MSG
IDC_LISTMSG ClistBox m_MSGS
?3. CAsyncSocket類用DoCallBack函數處理MFC消息,當一個網絡事件發生時,DoCallBack函數按網絡事件類型:FD_READ、FD_WRITE、FD_ACCEPT、FD_CONNECT分別調用OnReceive、OnSend、OnAccept、OnConnect函數。
由于MFC把這些事件處理函數定義為虛函數,所以要生成一個新的C++類,以重載這些函數,做法如下:
以Public方式繼承CAsyncSocket類,生成新類MySock;
為MySock類添加虛函數OnReceive、OnConnect、OnSend
4. 在MySock.h中添加以下代碼
public:
??????BOOL m_bConnected;????//是否連接
??????UINT m_nLength;????????//消息長度
??????char m_szBuffer[4096];????//消息緩沖區
5.??在MySock.ccp中添加以下代碼
原文:https://blog.csdn.net/baidu_19340981/article/details/39317125?
?
總結
以上是生活随笔為你收集整理的异步SOCKET与同步SOCKET的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于MFC的socket编程(异步非阻塞
- 下一篇: 运动估计简介