国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
孫鑫VC視頻教程筆記之第十六課(下)“異步套接字編程”
 

1.      異步套接字編程:

Windows套接字在兩種模式下執(zhí)行I/O操作,阻塞和非阻塞在阻塞模式下,在I/O操作完成前,執(zhí)行操作的Winsock函數(shù)會一直等待下去,不會立即返回程序(將控制權(quán)交還給程序)。而在非阻塞模式下,Winsock函數(shù)無論如何都會立即返回。采用異步套接字,可有效改善程序的運(yùn)行性能。

Windows Sockets為了支持Windows消息驅(qū)動機(jī)制,使應(yīng)用程序開發(fā)者能夠方便地處理網(wǎng)絡(luò)通信,它對網(wǎng)絡(luò)事件采用了基于消息的異步存取策略。

Windows Sockets的異步選擇函數(shù)WSAAsyncSelect()提供了消息機(jī)制的網(wǎng)絡(luò)事件選擇,當(dāng)使用它登記的網(wǎng)絡(luò)事件發(fā)生時(shí),Windows應(yīng)用程序相應(yīng)的窗口函數(shù)將收到一個消息,消息中指示了發(fā)生的網(wǎng)絡(luò)事件,以及與事件相關(guān)的一些信息。

      在上一章中編寫的Chat程序中,因?yàn)榻邮粘绦蚍旁诹艘粋€線程中,所以雖然它是阻塞的,也沒有影響到主線程的運(yùn)行性能。

 

2.      編寫基于異步套接字的聊天室程序:

a.      因?yàn)?/span>MFC自帶的AfxSocketInit函數(shù)初始化支持的是1.1版本的套接字,不適合異步套接字,我們需要調(diào)用的是Winsock2版本的套接字,那么加載套接字庫的過程只能使用WSAStartup了。在CChatAppInitInstance初始化函數(shù)中添加:

 

WORD wVersionRequested;

      WSADATA wsaData;

      int err;

     

      wVersionRequested = MAKEWORD( 2, 2 );

     

      err = WSAStartup( wVersionRequested, &wsaData );

      if ( err != 0 ) {

           return;

      }

     

     

      if ( LOBYTE( wsaData.wVersion ) != 2 ||

        HIBYTE( wsaData.wVersion ) != 2 ) {          

           WSACleanup( );

           return;

}

b.      StdAfx.h里添加#include <winsock2.h>,在setting里添加ws2_32.lib庫文件。

c.      CChatApp類添加析構(gòu)函數(shù),在其中添加WSACleanup來終止對套接字庫的使用。

d.      CChatDlg類添加成員變量SOCKET m_socket,并在構(gòu)造函數(shù)中初始化為0

e.      CChatDlg類添加析構(gòu)函數(shù),添加:

if(m_socket) //判斷socket是否有值

      closesocket(m_socket);

f.       創(chuàng)建初始化函數(shù)InitSocket(),代碼如下:

說明:在Winsock2版本中提供的WSASocket這樣一個擴(kuò)展方法用于創(chuàng)建套接字,對應(yīng)于socket方法;bind方法在winsock2中沒有提供相應(yīng)的擴(kuò)展方法。然后調(diào)用WSAAsyncSelect方法請求一個windows基于消息的網(wǎng)絡(luò)事件通知。

m_socket=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,0);

   if(INVALID_SOCKET==m_socket)

   {

        MessageBox("創(chuàng)建套接字失??!");

        return FALSE;

   }

  

   SOCKADDR_IN addrSock;

   addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

   addrSock.sin_family=AF_INET;

   addrSock.sin_port=htons(1234);

  

   int retVal;

   retVal=bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));

   if(SOCKET_ERROR==retVal)

   {

        MessageBox("套接字綁定失??!");

        return FALSE;

   }

說明:WSAAsyncSelect方法第二個參數(shù)表示網(wǎng)絡(luò)事件發(fā)生時(shí)用來接收消息的窗口,第三個參數(shù)表示處理響應(yīng)的消息,第四個參數(shù)表示網(wǎng)絡(luò)事件類型,采用或操作。我們當(dāng)前采用讀這樣一個事件,網(wǎng)絡(luò)上一旦有數(shù)據(jù)到來的時(shí)候就會觸發(fā)這個事件,系統(tǒng)就會通過我們自定義的消息UM_SOCK來通知我們進(jìn)行處理if(SOCKET_ERROR==WSAAsyncSelect(m_socket,m_hWnd,UM_SOCK,FD_READ))

            {

                 MessageBox("注冊網(wǎng)絡(luò)讀取事件失?。?/span>");

                 return FALSE;

   };

return TRUE;

g.      消息響應(yīng)函數(shù)的處理:

1.      創(chuàng)建自定以的消息UM_SOCK,注意:在消息響應(yīng)函數(shù)的申明中還是要添加WPARAMLPARAM參數(shù),因?yàn)榫W(wǎng)絡(luò)上的數(shù)據(jù)是通過這兩個參數(shù)傳遞給消息響應(yīng)函數(shù)進(jìn)行處理的。

2.      參看MSDNWSAAsyncSelect方法的說明如下:
When one of the nominated network events occurs on the specified socket s, the application's window hWnd receives messagewMsgThe wParam parameter identifies the socket on which a network event has occurred. The low word of lParam specifies the network event that has occurred. The high word of lParam contains any error code.

3.      WSARecvFrom函數(shù)的第二個參數(shù)可表示一個WSABUF的結(jié)構(gòu)體數(shù)組,可用于存放多個從網(wǎng)絡(luò)上接收到的信息塊,當(dāng)然也可以將所有信息放在一個結(jié)構(gòu)體中,然后將自己關(guān)心的信息塊取出,但這樣做比較麻煩,可以直接用WSABUF結(jié)構(gòu)體數(shù)組接收不同信息的塊即可。(沒有具體的實(shí)際操作經(jīng)驗(yàn))

在消息響應(yīng)函數(shù)中添加如下代碼

switch(LOWORD(lParam)) { //lParam的低字節(jié)指明網(wǎng)絡(luò)事件的類型

      case FD_READ: //我們當(dāng)前只有讀取這樣一個事件,這是在WSAAsyncSelect中設(shè)定的

           WSABUF wsabuf;

           wsabuf.buf=new char[200]; //網(wǎng)絡(luò)上接收到的數(shù)據(jù)

           wsabuf.len=200;

           DWORD dwRead;

           DWORD dwFlag=0;

           SOCKADDR_IN addrFrom;

           int len=sizeof(addrFrom);

           CString str;

            if(SOCKET_ERROR==WSARecvFrom(m_socket,&wsabuf,1,&dwRead,&dwFlag,(SOCKADDR*)&addrFrom,&len,NULL,NULL))

           {

                 //下面的消息框基本不會運(yùn)行,因?yàn)?/span>WSARecvFrom方法是在有網(wǎng)絡(luò)數(shù)據(jù)的情況下才會被調(diào)用的,所以運(yùn)行到這段,基本是有數(shù)據(jù)的,做這樣一個判斷,只是出于編程風(fēng)格一致而已

                 MessageBox("接收數(shù)據(jù)失敗!");

                 return;

           }

      str.Format("from %s said:%s",inet_ntoa(addrFrom.sin_addr),wsabuf.buf);

           CString temp;

           GetDlgItemText(IDC_EDIT_RECV,temp);

           temp+="\r\n"+str;

           SetDlgItemText(IDC_EDIT_RECV,temp);

           break;

}

h.      信息的發(fā)送:

DWORD dwIP; //控件上填寫的IP地址

   CString strSend; //需要發(fā)送的信息內(nèi)容

   WSABUF wsbuf; //需要發(fā)送的信息內(nèi)容

   DWORD dwSend;

   ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);

   GetDlgItemText(IDC_EDIT_SEND,strSend);

 

   SOCKADDR_IN addrTo;

   addrTo.sin_addr.S_un.S_addr=htonl(dwIP);

   addrTo.sin_family=AF_INET;

   addrTo.sin_port=htons(1234);

 

   //GetBuffer函數(shù)將CString類型轉(zhuǎn)換為char*類型

   wsbuf.buf=strSend.GetBuffer(strSend.GetLength());

   wsbuf.len=strSend.GetLength()+1; //多一個字節(jié)用于存放結(jié)束操作符

   if(SOCKET_ERROR==WSASendTo(m_socket,&wsbuf,1,&dwSend,0,(SOCKADDR*)&addrTo,sizeof(SOCKADDR),NULL,NULL))

   {

        MessageBox("發(fā)送數(shù)據(jù)失敗!");

        return;

   }

   else

   {

        SetDlgItemText(IDC_EDIT_SEND,"");

}

i.        綜上所述,創(chuàng)建一個基于winsock2版本的異步套接字的網(wǎng)絡(luò)聊天室程序有以下幾個步驟:

1.      調(diào)用WSAStartup加載套接字庫

2.      調(diào)用WSASocket創(chuàng)建套接字

3.     調(diào)用WSAAsyncSelect請求基于windows消息的網(wǎng)絡(luò)事件通知

4.      創(chuàng)建自定義的消息響應(yīng)函數(shù),來處理捕獲的網(wǎng)絡(luò)事件

5.      在消息響應(yīng)函數(shù)內(nèi)部調(diào)用WSARecvFrom來處理接收到的數(shù)據(jù)

6.      調(diào)用WSASendTo處理發(fā)送數(shù)據(jù)

3.      小結(jié):

當(dāng)前程序?qū)⑾⒌慕邮蘸桶l(fā)送放在了同一個線程中,即主線程中。如果采用先前使用過的阻塞套接字的話,程序會因?yàn)榻邮蘸瘮?shù)的調(diào)用導(dǎo)致主線程的暫停運(yùn)行,就無法及時(shí)的發(fā)送消息了。但是采用異步套接字可使得發(fā)送和接收放在同一個線程中而不會有相互的影響。

如果采用異步套接字加上多線程編程,則大大會提高網(wǎng)絡(luò)運(yùn)用程序的性能。

在第十四課中講winsock1.1的編程中一般將接收函數(shù)放在一個while循環(huán)中,來使得程序一直處于接收響應(yīng)狀態(tài),在異步套接字中,利用了在程序初始化的時(shí)候調(diào)用了WSAAsyncSelect方法來聲明程序的網(wǎng)絡(luò)的事件有相應(yīng)的自定義消息來處理,其真正的核心部分還是封裝在MFC

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
如何在Python中創(chuàng)建WEB應(yīng)用程序
Windows Socket API 使用經(jīng)驗(yàn) - 技術(shù)文檔 - VC文檔 - 網(wǎng)絡(luò)通訊 - 立華軟件園
1、socket是什么?套接字是什么?
云風(fēng)的 BLOG: Go 語言初步
Windows 下的socket(套接字編程)
UDP Socket寫通信程序是不是只要直接發(fā)送就可以了?
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服