乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器

       禁忌石 2017-05-20

      MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
      聽語音

      • |
      • 瀏覽:7267
      • |
      • 更新:

      Windows程序開發(fā)中,如果涉及到網(wǎng)絡(luò)編程的話,一般少不了socket,socket作為應(yīng)用層與傳輸層之間的一個(gè)抽象層,可以理解為應(yīng)用程序與網(wǎng)絡(luò)協(xié)議之間的編程接口。

      我曾通過MFC開發(fā)了一個(gè)簡單C/S(客戶端/服務(wù)器)模式的應(yīng)用程序,主要是為了實(shí)現(xiàn)手機(jī)控制電腦,android網(wǎng)絡(luò)編程也可以通過socket實(shí)現(xiàn),這里以PC端編寫服務(wù)器程序和客戶端程序?yàn)槔f明socket編程的一般步驟。

      MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器

      工具/原料

      • Visual Studio 2010/2013

      創(chuàng)建項(xiàng)目

      1. 1

        首先創(chuàng)建一個(gè)MFC項(xiàng)目,修改名稱以及存放路徑。

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
      2. 2

        項(xiàng)目配置,在向?qū)н^程中選擇“基于對話框”模式,并選擇“windows”套接字。

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
      3. 3

        設(shè)計(jì)服務(wù)器界面,控件有:4個(gè)靜態(tài)文本(Static Text),最后一個(gè)用于指示用戶連接個(gè)數(shù);一個(gè)按鈕(Button),用于打開或關(guān)閉服務(wù)器;2個(gè)編輯框(Edit Control),一個(gè)用于輸入端口號,另一個(gè)只讀的用于顯示事件日志。

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
      4. 4

        修改各個(gè)控件的屬性,注意編輯框2還要把Multiline和Vertical Scroll屬性選為true,以實(shí)現(xiàn)多行顯示并自帶滾動條。

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
      5. 5

        1、 給控件添加變量和事件處理函數(shù),這個(gè)通過類向?qū)Ь涂梢酝瓿?,變量如上表所示,事件只有“按鈕按下”一個(gè),雙擊按鈕自動生成函數(shù),后面添加相關(guān)代碼即可。

        2、 在類視圖中添加一個(gè)新類CServerSocket,派生于CSocket類,對該類進(jìn)行類向?qū)砑尤齻€(gè)函數(shù):

        OnAccept()、OnClose()、OnReceive()

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
        END

      編寫服務(wù)器類

      1. 1

        看看CServerSocket的類視圖,需要修改的有之前生成的三個(gè)函數(shù)。

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
      2. 2

        修改頭文件ServerSocket.h,定義主對話框的指針變量

        #pragma once

        #include "PhoneServerDlg.h"                              // 主對話框頭文件

        class CPhoneServerDlg;                                      //別忘了加上   

        class CServerSocket : public CSocket

        {

        public:

                 CPhoneServerDlg* m_pDlg;                       // 主對話框指針對象

                 CServerSocket();

                 virtual ~CServerSocket();

                 virtual void OnReceive(int nErrorCode);

                 virtual void OnClose(int nErrorCode);

                 virtual void OnAccept(int nErrorCode);

        };

      3. 3

        修改源文件ServerSocket.cpp,注意其中調(diào)用的函數(shù)都在主對話框類中定義。

        void CServerSocket::OnReceive(int nErrorCode)

        {

                 m_pDlg->RecvData(this);                           // 接收數(shù)據(jù)

                 CSocket::OnReceive(nErrorCode);

        }

        void CServerSocket::OnClose(int nErrorCode)

        {

                 m_pDlg->RemoveClient(this);                   // 刪除下線用戶

                 CSocket::OnClose(nErrorCode);

        }

        void CServerSocket::OnAccept(int nErrorCode)

        {

                 m_pDlg->AddClient();                                  //添加上線用戶

                 CSocket::OnAccept(nErrorCode);

        }

        至此,CServerSocket類的代碼就完成了,接下來編寫主類相關(guān)函數(shù)。

        END

      編寫主對話框類

      1. 1

        修改頭文件PhoneServerDlg.h 

        1、   添加服務(wù)器類的頭文件。

        #include "ServerSocket.h"

        class CServerSocket;                  //一定要加上

        2、   添加函數(shù)聲明和變量定義

        CServerSocket* listenSocket;     // 用于打開服務(wù)器

        CPtrList m_clientList;                 // 鏈表用于存儲用戶

        bool m_connect;                       // 用于標(biāo)記服務(wù)器狀態(tài)

        void AddClient();                       // 增加用戶,響應(yīng)用戶請求

        void RemoveClient(CServerSocket* pSocket);          // 移除下線的用戶

        void RecvData(CServerSocket* pSocket);                 // 獲取數(shù)據(jù)

        void UpdateEvent(CString str);  // 更新事件日志

        BOOL WChar2MByte(LPCWSTR srcBuff, LPSTR destBuff, int nlen);        

        //字符轉(zhuǎn)換

        void SendMSG(CString str);       // 發(fā)送消息給各個(gè)客戶端

        void ControlPC(CString AndroidControl);  // 手機(jī)控制PC的響應(yīng)函數(shù)

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
      2. 2

        修改PhoneServerDlg.cpp實(shí)現(xiàn)頭文件中聲明的函數(shù)

        1、 首先實(shí)現(xiàn)“打開服務(wù)器”按鈕的響應(yīng)函數(shù)

        void CPhoneServerDlg::OnBnClickedStartserver()

        {

                 // TODO:  在此添加控件通知處理程序代碼

                 if (m_connect)

                 {

                           delete listenSocket;

                           listenSocket = NULL;

                           m_connect = false;

                           SetDlgItemText(IDC_StartServer, _T("打開服務(wù)器"));

                           UpdateEvent(_T("系統(tǒng)關(guān)閉服務(wù)器."));

                           return;

                 }

                 listenSocket = new CServerSocket();

                 listenSocket->m_pDlg = this;

        // 指定對話框?yàn)橹鲗υ捒?,不能少了這句

                 UpdateData(true);

                 if (!listenSocket->Create(m_port))                     

        // 創(chuàng)建服務(wù)器的套接字,IP地址默認(rèn)本機(jī)IP

                 {

                           AfxMessageBox(_T("創(chuàng)建套接字錯(cuò)誤!"));

                           listenSocket->Close();

                           return;

                 }

                 if (!listenSocket->Listen())

                 {

                           AfxMessageBox(_T("監(jiān)聽失敗!"));

                           listenSocket->Close();

                           return;

                 }

                 m_connect = true;

                 SetDlgItemText(IDC_StartServer, _T("關(guān)閉服務(wù)器"));

                 UpdateEvent(_T("系統(tǒng)打開服務(wù)器."));

        }

        說明:本函數(shù)用于打開或關(guān)閉服務(wù)器,主要用到Create函數(shù)和Listen函數(shù)用于創(chuàng)建服務(wù)器和監(jiān)聽客戶端。其中端口號從編輯框獲取,應(yīng)用程序的可用端口范圍是1024-65535。

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
      3. 3

        2、 編寫AddClient函數(shù),用于增加用戶,響應(yīng)用戶請求

        void CPhoneServerDlg::AddClient()

        {

                 CServerSocket *pSocket = new CServerSocket;

                 pSocket->m_pDlg = this;

                 listenSocket->Accept(*pSocket);

                 pSocket->AsyncSelect(FD_READ | FD_WRITE | FD_CLOSE);

                 m_clientList.AddTail(pSocket);

                 m_userCount = m_clientList.GetCount();

                 UpdateData(false);

                 UpdateEvent(_T("用戶連接服務(wù)器."));

                 SendMSG(_T("Hello!"));

        }

        說明:本函數(shù)在CServerSocket類中的OnAccept消息中調(diào)用,用于響應(yīng)用戶連接服務(wù)器的請求,主要函數(shù)為Accept,當(dāng)連接成功后,通過鏈表m_clientList保存新用戶,更新日志,向新用戶發(fā)送“Hello”表示歡迎。

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
      4. 4

        3、 編寫RemoveClient函數(shù),用于移除下線的用戶

        void CPhoneServerDlg::RemoveClient(CServerSocket* pSocket)

        {

                 POSITION nPos = m_clientList.GetHeadPosition();

                 POSITION nTmpPos = nPos;

                 while (nPos)

                 {

                           CServerSocket* pSockItem = (CServerSocket*)m_clientList.GetNext(nPos);

                           if (pSockItem->m_hSocket == pSocket->m_hSocket)

                           {                          

                                    pSockItem->Close();

                                    delete pSockItem;

                                    m_clientList.RemoveAt(nTmpPos);

                                    m_userCount = m_clientList.GetCount();

                                    UpdateData(false);

                                    UpdateEvent(_T("用戶離開."));

                                    return;

                           }

                           nTmpPos = nPos;

                 }

        }

        說明:本函數(shù)在CServerSocket類中的OnClose消息中調(diào)用,用到POSITION結(jié)構(gòu),查找存儲用戶中哪位用戶下線了,將下線用戶釋放,從鏈表中刪除,并更新日志。

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
      5. 5

        4、  編寫RecvData函數(shù),用于獲取數(shù)據(jù)

        void CPhoneServerDlg::RecvData(CServerSocket* pSocket)

        {

                 char* pData = NULL;

                 pData = new char[1024];

                 memset(pData, 0, sizeof(char)* 1024);

                 UCHAR leng = 0;

                 CString str;

                 if (pSocket->Receive(pData, 1024, 0) != SOCKET_ERROR)

                 {

                           str = pData;

                           ControlPC(str);     // 依據(jù)指令控制電腦

                           SendMSG(str);     // 轉(zhuǎn)發(fā)數(shù)據(jù)給所有用戶,包括發(fā)送數(shù)據(jù)的用戶

                 }

                 delete pData;

                 pData = NULL;

        }

        說明:本函數(shù)在CServerSocket類中的OnReceive消息中調(diào)用,用于處理接收到的數(shù)據(jù)并控制電腦,并將數(shù)據(jù)轉(zhuǎn)發(fā)給所有用戶(類似于群消息),通過CSocket類的GetPeerName函數(shù)可以獲取用戶的IP和端口號。

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
      6. 6

        5、  編寫UpdateEvent函數(shù),用于更新事件日志

        void CPhoneServerDlg::UpdateEvent(CString str)

        {

                 CString string;

                 CTime time = CTime::GetCurrentTime();                  

        // 獲取系統(tǒng)當(dāng)前時(shí)間

                 str += _T("\r\n");                                                             

        // 用于換行顯示日志

                 string = time.Format(_T("%Y/%m/%d %H:%M:%S  ")) + str;         

        // 格式化當(dāng)前時(shí)間

                 int lastLine = m_event.LineIndex(m_event.GetLineCount() - 1);

        //獲取編輯框最后一行索引

                 m_event.SetSel(lastLine+1,lastLine+2,0);                                     

        //選擇編輯框最后一行

                 m_event.ReplaceSel(string);                                                             //替換所選那一行的內(nèi)容

        }

        說明:本函數(shù)在所有需要更新日志的地方都有調(diào)用,方便服務(wù)器記錄用戶的登錄和退出事件。

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
      7. 7

        6、  編寫WChar2MByte函數(shù),用于實(shí)現(xiàn)字符轉(zhuǎn)換

        BOOL CPhoneServerDlg::WChar2MByte(LPCWSTR srcBuff, LPSTR destBuff, int nlen)

        {

                 int n = 0;

                 n = WideCharToMultiByte(CP_OEMCP, 0, srcBuff, -1, destBuff, 0, 0, FALSE);

                 if (n<nlen)return FALSE;

                 WideCharToMultiByte(CP_OEMCP, 0, srcBuff, -1, destBuff, nlen, 0, FALSE);

                 return TRUE;

        }

        說明:本函數(shù)在發(fā)送函數(shù)SendMSG中調(diào)用,用于字符集的轉(zhuǎn)換,將寬字符轉(zhuǎn)換為多字符集,不經(jīng)轉(zhuǎn)換的話,接收方只能接收一個(gè)字節(jié)。

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
      8. 8

        7、  編寫SendMSG函數(shù),用于發(fā)送消息給各個(gè)客戶端

        void CPhoneServerDlg::SendMSG(CString str)

        {

                 char *pSend = new char[str.GetLength()];

                 memset(pSend, 0, str.GetLength()*sizeof(char));

                 if (!WChar2MByte(str.GetBuffer(0), pSend, str.GetLength()))

                 {

                           AfxMessageBox(_T("字符轉(zhuǎn)換失敗"));

                           delete pSend;

                           return;

                 }

                 POSITION nPos = m_clientList.GetHeadPosition();

                 while (nPos)

                 {

                           CServerSocket* pTemp = (CServerSocket*)m_clientList.GetNext(nPos);

                           pTemp->Send(pSend, str.GetLength());

                 }

                 delete pSend;

        }

        說明:發(fā)送函數(shù),用于發(fā)送消息給所有用戶,主要函數(shù)為Send,在AddClient和RecvData中都有調(diào)用,可以隨時(shí)調(diào)用發(fā)消息給用戶。

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
      9. 9

        8、 編寫ControlPC函數(shù),用于處理接收到的指令并控制電腦,主要是為了實(shí)現(xiàn)手機(jī)控制而寫。

        void CPhoneServerDlg::ControlPC(CString AndroidControl)

        {

                 if (AndroidControl == "mop")             //打開播放器

                 {

                 ShellExecute(NULL, _T("open"), _T("C:\\Program Files (x86)\\KuGou\\KGMusic\\KuGou.exe"), NULL, NULL, SW_SHOWNORMAL);

                 }

                 else if (AndroidControl == "mcl")         //關(guān)閉播放器

                 {

                           DWORD id_num;

                           HWND hWnd = ::FindWindow(_T("kugou_ui"), NULL);

                           GetWindowThreadProcessId(hWnd, &id_num);                      

        //注意:第二個(gè)參數(shù)是進(jìn)程的ID,返回值是線程的ID。

                           HANDLE hd = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id_num);

                           TerminateProcess(hd, 0);

                 }

                 else if (AndroidControl == "mpl" || AndroidControl == "mpa")                //播放/暫停

                 {

                           keybd_event(VK_LMENU, 0, 0, 0);

                           keybd_event(VK_F5, 0, 0, 0);

                           keybd_event(VK_F5, 0, KEYEVENTF_KEYUP, 0);

                           keybd_event(VK_LMENU, 0, KEYEVENTF_KEYUP, 0);

                 }

        }

        說明:控制功能可以自己隨意添加,這里只以音樂播放為例進(jìn)行說明,ShellExecute函數(shù)用于調(diào)用其他應(yīng)用程序,關(guān)閉進(jìn)程比較麻煩一點(diǎn),這里先獲取應(yīng)用程序窗口的ID,通過OpenProcess和TerminateProcess終止進(jìn)程。

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
      10. 10

        9、 類向?qū)砑犹摵瘮?shù)PreTranslateMessage,并編寫代碼

        BOOL CPhoneServerDlg::PreTranslateMessage(MSG* pMsg)

        {

                 switch (pMsg->wParam)

                 {

                 case VK_RETURN:

                 case VK_ESCAPE:

                           return true; break;

                 }

                 return CDialogEx::PreTranslateMessage(pMsg);

        }

        說明:該函數(shù)用于防止按下enter或者esc時(shí)退出程序。

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
      11. 11

        經(jīng)過以上步驟,服務(wù)器端的程序就完成了,雖然函數(shù)有點(diǎn)多,但只要理解了socket的使用流程并不難,總體可以概括為4步:

        1、創(chuàng)建服務(wù)器

        2、連接請求連接的客戶端

        3、與客戶端進(jìn)行數(shù)據(jù)傳輸(發(fā)送和接收)

        4、客戶端斷開服務(wù)器

        加上一些輔助代碼,可以更好的實(shí)現(xiàn)網(wǎng)絡(luò)通訊。客戶端的程序會在下一篇經(jīng)驗(yàn)中介紹。

        MFC/Socket網(wǎng)絡(luò)編程:[1]服務(wù)器
        END

      注意事項(xiàng)

      • 注意類與類之間頭文件的引用
      • 如果不重寫虛函數(shù)PreTranslateMessage會導(dǎo)致按下回車或者esc時(shí)自動退出程序
      • 合理設(shè)置端口號,不要與其他程序發(fā)生沖突

        本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多