日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Socket重叠IO

發(fā)布時(shí)間:2024/4/11 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Socket重叠IO 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.為什么到現(xiàn)在才弄懂這個(gè)

不知道這個(gè)Socket重疊IO這種模型是不是socket IO完成端口的基礎(chǔ),不過我感覺,學(xué)習(xí)一下這個(gè)再去學(xué)習(xí)socket IO完成端口是比較有好處的。

這個(gè)Scoket重疊IO我以前記得看過好幾次,都沒看懂。一部分原因是我沒能靜態(tài)心來寫代碼,還有更重要的原因就是,Socket重疊他們的結(jié)構(gòu)體參數(shù),還有傳參數(shù)讓人很難理解。下面我將對(duì)這些數(shù)據(jù)結(jié)構(gòu)和參數(shù)進(jìn)行一下講解

2.初識(shí)WSARecv 函數(shù)

?

int WSARecv(SOCKET s,//要接收消息的socketLPWSABUF lpBuffers, //一個(gè)結(jié)構(gòu)體數(shù)組。當(dāng)接收IO操作完畢后接收內(nèi)容就在這個(gè)里面了DWORD dwBufferCount, //要接多少個(gè)WSABUFLPDWORD lpNumberOfBytesRecvd,//接收了多少個(gè)字節(jié) LPDWORD lpFlags,LPWSAOVERLAPPED lpOverlapped,//Overlapped結(jié)構(gòu)體指針LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine//在本節(jié)用不用);

lpBuffers參數(shù):這是一WSABUF數(shù)組,意思是這個(gè)函數(shù)可以接收不止一個(gè)字符緩沖,但是我們一般用一個(gè)就夠了。 接收多個(gè)我還沒能測(cè)試

dwBufferCount參數(shù):是指上一個(gè)參數(shù)的數(shù)組個(gè)數(shù)

lpOverlapped參數(shù):這個(gè)參數(shù)是Overlappad結(jié)構(gòu)體指針,這個(gè)指針當(dāng)IO操作完畢的時(shí)候,這里會(huì)被系統(tǒng)填充。當(dāng)IO操作完成時(shí)這個(gè)結(jié)構(gòu)也可以通過WSAGetOverlappedResult得到

返回值:

0:沒有錯(cuò)誤發(fā)生,IO操作當(dāng)即完成

SOCKET_ERROR:發(fā)生錯(cuò)誤

如果是SOCKET_ERROR并且WSAGetLastError() == WSA_IO_PENDING 這時(shí)表示操作已經(jīng)提交。異步操作大部分都是這樣的。

3.何時(shí)得到收取的消息,然后取出消息

當(dāng)異常操作完成時(shí),Overlapped的hEvent這個(gè)事件會(huì)觸發(fā)。這時(shí)Overlapped的InternalHigh表示接受的字節(jié)數(shù)。Internal表示錯(cuò)誤代碼。消息的內(nèi)容即是你當(dāng)初調(diào)用WSARecv時(shí)傳入的lpBuffers參數(shù)。

4.代碼組織

以服務(wù)端為例

首先傳入WSARecv的幾個(gè)參數(shù)必定與一個(gè)socket關(guān)聯(lián)。而且這些參數(shù)在異步調(diào)用完成之后,但是以后還要用(在WaitForMutiObjects時(shí)要用到),而且每一個(gè)socket得擁有一個(gè)不同的Event來標(biāo)識(shí)是哪個(gè)客戶端來消息了。所以為每一個(gè)客戶端socket構(gòu)造一個(gè)Overlapped結(jié)構(gòu)。比如我測(cè)試的代碼中每一個(gè)客戶端都有這樣一個(gè)結(jié)構(gòu)體,而且當(dāng)accept來的時(shí)候表示有新的socket連接,就得生成這樣一個(gè)結(jié)構(gòu)體,當(dāng)客戶端掉線的時(shí)候,就得刪除這樣一個(gè)結(jié)構(gòu)體

下面就是這個(gè)結(jié)構(gòu)體:

struct CClientInfo { public:CClientInfo() {ZeroMemory(&m_ol,sizeof(m_ol));ZeroMemory(m_szBuf,256);m_ol.hEvent = WSACreateEvent();}~CClientInfo(){WSACloseEvent(m_ol.hEvent);}WSAOVERLAPPED m_ol;SOCKET sSocket;CString strIp;u_short nPort;CString GetShowText();char m_szBuf[256]; };

?

下面是兩個(gè)函數(shù),一個(gè)是當(dāng)客戶端連接的時(shí)候,一個(gè)是當(dāng)客戶端斷開的時(shí)候

CClientInfo * CServerDlg::OnSocketConnected(SOCKET sClientSocket,sockaddr_in * saClient) {u_short uPort = ntohs(((sockaddr_in *)saClient)->sin_port);CString strIp = CA2T(inet_ntoa(((sockaddr_in *)saClient)->sin_addr));CClientInfo * pClientInfo = new CClientInfo;pClientInfo->nPort = uPort;pClientInfo->strIp = strIp;pClientInfo->sSocket = sClientSocket;LockClientArray();m_ClientArray.Add(pClientInfo);int nIndexInserted = m_ClientListBox.AddString(pClientInfo->GetShowText());m_ClientListBox.SetItemData(nIndexInserted,pClientInfo->sSocket);UnLockClientArray();return pClientInfo; }void CServerDlg::OnSocketDisconnect(SOCKET aClientSocket) {LockClientArray();for(int i = 0;i<m_ClientArray.GetCount();i++){CClientInfo * pClientInfo = m_ClientArray.GetAt(i);if(pClientInfo->sSocket == aClientSocket){m_ClientListBox.DeleteString(m_ClientListBox.FindString(0,pClientInfo->GetShowText()));delete pClientInfo;m_ClientArray.RemoveAt(i);break;}}UnLockClientArray(); }

5.沒有測(cè)試的內(nèi)容和疑問

發(fā)送的時(shí)候沒有用WSASend,以后再學(xué)習(xí)

6.注意

當(dāng)使用AcceptEx之后,一般用GetAcceptExSockaddrs這個(gè)函數(shù)來得到本地或者遠(yuǎn)程的地址信息。但也可以調(diào)用getsockname這個(gè)函數(shù),前提是,必須先給接受到socket設(shè)置一個(gè)SO_UPDATE_ACCEPT_CONTEXT。

7.AcceptEx用法

BOOL AcceptEx(
? __in????????? SOCKET sListenSocket,
? __in????????? SOCKET sAcceptSocket,
? __in????????? PVOID lpOutputBuffer,
? __in????????? DWORD dwReceiveDataLength,
? __in????????? DWORD dwLocalAddressLength,
? __in????????? DWORD dwRemoteAddressLength,
? __out???????? LPDWORD lpdwBytesReceived,
? __in????????? LPOVERLAPPED lpOverlapped
);

● sListenSocket 參數(shù)指定的是一個(gè)監(jiān)聽套接字。
● sAcceptSocket 參數(shù)指定的是另一個(gè)套接字,負(fù)責(zé)對(duì)進(jìn)入連接請(qǐng)求的“接受”。
AcceptEx 函數(shù)和 accept 函數(shù)的區(qū)別在于,我們必須提供接受的套接字,而不是讓函數(shù)自動(dòng)為我們創(chuàng)建。
正是由于要提供套接字,所以要求我們事先調(diào)用 socket 或 WSASocket 函數(shù),創(chuàng)建一個(gè)套接字,以便通過 sAcceptSocket 參數(shù),將其傳遞給 AcceptEx。
● lpOutputBuffer 參數(shù)指定的是一個(gè)特殊的緩沖區(qū),因?yàn)樗?fù)責(zé)三種數(shù)據(jù)的接收:服務(wù)器的本地地址,客戶機(jī)的遠(yuǎn)程地址,以及在新建連接上發(fā)送的第一個(gè)數(shù)據(jù)塊。
● dwReceiveDataLength參數(shù)以字節(jié)為單位,指定了在 lpOutputBuffer 緩沖區(qū)中,保留多大的空間,用于數(shù)據(jù)的接收。
如這個(gè)參數(shù)設(shè)為0,那么在連接的接受過程中,不會(huì)再一道接收任何數(shù)據(jù)。
● dwLocalAddressLength 和 dwRemoteAddressLength 參數(shù)也是以字節(jié)為單位,指定在 lpOutputBuffer 緩沖區(qū)中,保留多大的空間,
在一個(gè)套接字被接受的時(shí)候,用于本地和遠(yuǎn)程地址信息的保存。

要注意的是,和當(dāng)前采用的傳送協(xié)議允許的最大地址長(zhǎng)度比較起來,這里指定的緩沖區(qū)大小至少應(yīng)多出16字節(jié)。
舉個(gè)例子來說:假定正在使用的是 TCP/IP 協(xié)議,那么這里的大小應(yīng)設(shè)為“SOCKADDRIN 結(jié)構(gòu)的長(zhǎng)度+16字節(jié)”。

● lpdwBytesReceived 參數(shù)用于返回接收到的實(shí)際數(shù)據(jù)量,以字節(jié)為單位。
只有在操作以同步方式完成的前提下,才會(huì)設(shè)置這個(gè)參數(shù)。假如 AcceptEx 函數(shù)返回 ERROR_IO_PENDING,
那么這個(gè)參數(shù)永遠(yuǎn)都不會(huì)設(shè)置,我們必須利用完成事件通知機(jī)制,獲知實(shí)際讀取的字節(jié)量。

● lpOverlapped 參數(shù)對(duì)應(yīng)的是一個(gè) OVERLAPPED 結(jié)構(gòu),允許 AcceptEx 以一種異步方式工作。
如我們?cè)缦人?#xff0c;只有在一個(gè)重疊 I/O 應(yīng)用中,該函數(shù)才需要使用事件對(duì)象通知機(jī)制,這是由于此時(shí)沒有一個(gè)完成例程參數(shù)可供使用。
也就是說 AcceptEx 函數(shù)只能由本節(jié)課給大家講的“事件通知”方式獲取異步 I/O 請(qǐng)求的結(jié)果,而“完成例程”方法無法被使用。

8.源代碼

源碼下載 vs2012項(xiàng)目

.h文件

// ServerDlg.h : 頭文件 // #pragma once#include "afxwin.h" #include <Winsock2.h> #pragma comment(lib,"Ws2_32.lib")#define WM_SOCKET WM_USER+220enum IO_TYPE {IO_RECV,IO_ACCEPT,IO_UNKNOW };// CServerDlg 對(duì)話框 struct CClientInfo { public:CClientInfo() {ZeroMemory(&m_ol,sizeof(m_ol));ZeroMemory(m_szBuf,256);sAcceptSocket = INVALID_SOCKET;m_ol.hEvent = WSACreateEvent();m_IO_type = IO_UNKNOW;}~CClientInfo(){WSACloseEvent(m_ol.hEvent);}WSAOVERLAPPED m_ol;SOCKET sSocket;SOCKET sAcceptSocket;CString strIp;u_short nPort;CString GetShowText();char m_szBuf[256];IO_TYPE m_IO_type; };class CServerDlg : public CDialogEx { // 構(gòu)造 public:CServerDlg(CWnd* pParent = NULL); // 標(biāo)準(zhǔn)構(gòu)造函數(shù)~CServerDlg(); // 對(duì)話框數(shù)據(jù)enum { IDD = IDD_SERVER_DIALOG };protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持// 實(shí)現(xiàn) protected:HICON m_hIcon;// 生成的消息映射函數(shù)virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();DECLARE_MESSAGE_MAP()public:afx_msg void OnBnClickedButton1();void InitSocket();SOCKET m_ServerSocket;CClientInfo * OnSocketConnected(SOCKET sClientSocket,sockaddr_in * saClient);void OnSocketDisconnect(SOCKET aClientSocket);CListBox m_ClientListBox;CArray<CClientInfo *> m_ClientArray;CListBox m_RecvMsgListBox;CRITICAL_SECTION m_CS_ClientArray;void LockClientArray(){EnterCriticalSection(&m_CS_ClientArray);}void UnLockClientArray(){LeaveCriticalSection(&m_CS_ClientArray);}afx_msg void OnBnClickedButton3();void PostRecv(CClientInfo * p);BOOL PostAccept(SOCKET sListenSocket);BOOL PostAccept(CClientInfo * p);void OnError(); };

.cpp文件

// ServerDlg.cpp : 實(shí)現(xiàn)文件 // #include "stdafx.h" #include "Server.h" #include "ServerDlg.h" #include "afxdialogex.h" #include <Mswsock.h>#ifdef _DEBUG #define new DEBUG_NEW #endif// 用于應(yīng)用程序“關(guān)于”菜單項(xiàng)的 CAboutDlg 對(duì)話框class CAboutDlg : public CDialogEx { public:CAboutDlg();// 對(duì)話框數(shù)據(jù)enum { IDD = IDD_ABOUTBOX };protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持// 實(shí)現(xiàn) protected:DECLARE_MESSAGE_MAP() };CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD) { }void CAboutDlg::DoDataExchange(CDataExchange* pDX) {CDialogEx::DoDataExchange(pDX); }BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) END_MESSAGE_MAP()// CServerDlg 對(duì)話框 CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/): CDialogEx(CServerDlg::IDD, pParent) {m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);m_ServerSocket = INVALID_SOCKET;InitializeCriticalSection(&m_CS_ClientArray); } CServerDlg::~CServerDlg() {DeleteCriticalSection(&m_CS_ClientArray); } void CServerDlg::DoDataExchange(CDataExchange* pDX) {CDialogEx::DoDataExchange(pDX);DDX_Control(pDX, IDC_LIST_CLIENT_LIST, m_ClientListBox);DDX_Control(pDX, IDC_LIST_RECV, m_RecvMsgListBox); }BEGIN_MESSAGE_MAP(CServerDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BUTTON1, &CServerDlg::OnBnClickedButton1)ON_BN_CLICKED(IDC_BUTTON3, &CServerDlg::OnBnClickedButton3) END_MESSAGE_MAP()// CServerDlg 消息處理程序 BOOL CServerDlg::OnInitDialog() {CDialogEx::OnInitDialog();// 將“關(guān)于...”菜單項(xiàng)添加到系統(tǒng)菜單中。// IDM_ABOUTBOX 必須在系統(tǒng)命令范圍內(nèi)。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 設(shè)置此對(duì)話框的圖標(biāo)。當(dāng)應(yīng)用程序主窗口不是對(duì)話框時(shí),框架將自動(dòng)// 執(zhí)行此操作SetIcon(m_hIcon, TRUE); // 設(shè)置大圖標(biāo)SetIcon(m_hIcon, FALSE); // 設(shè)置小圖標(biāo)// TODO: 在此添加額外的初始化代碼 InitSocket();SetDlgItemInt(IDC_EDIT_PORT,10103);return TRUE; // 除非將焦點(diǎn)設(shè)置到控件,否則返回 TRUE }void CServerDlg::OnSysCommand(UINT nID, LPARAM lParam) {if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialogEx::OnSysCommand(nID, lParam);} }// 如果向?qū)υ捒蛱砑幼钚』粹o,則需要下面的代碼 // 來繪制該圖標(biāo)。對(duì)于使用文檔/視圖模型的 MFC 應(yīng)用程序, // 這將由框架自動(dòng)完成。void CServerDlg::OnPaint() {if (IsIconic()){CPaintDC dc(this); // 用于繪制的設(shè)備上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使圖標(biāo)在工作區(qū)矩形中居中int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// 繪制圖標(biāo) dc.DrawIcon(x, y, m_hIcon);}else{CDialogEx::OnPaint();} }//當(dāng)用戶拖動(dòng)最小化窗口時(shí)系統(tǒng)調(diào)用此函數(shù)取得光標(biāo) //顯示。 HCURSOR CServerDlg::OnQueryDragIcon() {return static_cast<HCURSOR>(m_hIcon); }CString CClientInfo::GetShowText() {CString strItemText;strItemText.Format(_T("%s:%d"),strIp,nPort);return strItemText; }CClientInfo * CServerDlg::OnSocketConnected(SOCKET sClientSocket,sockaddr_in * saClient) {BOOL bDelete = FALSE;if(saClient == NULL){sockaddr_in * pTempClientAddr = new sockaddr_in;int nLen = sizeof(sockaddr_in);if(SOCKET_ERROR == getpeername(sClientSocket,(sockaddr*)pTempClientAddr,&nLen)){int nErrorCode = ::WSAGetLastError();if(SOCKET_ERROR == getpeername(sClientSocket,(sockaddr*)pTempClientAddr,&nLen))OutputDebugStringA("Failed!\n");}saClient = (sockaddr_in*)pTempClientAddr;bDelete = TRUE;}u_short uPort = ntohs(((sockaddr_in *)saClient)->sin_port);CString strIp = CA2T(inet_ntoa(((sockaddr_in *)saClient)->sin_addr));CClientInfo * pClientInfo = new CClientInfo;pClientInfo->nPort = uPort;pClientInfo->strIp = strIp;pClientInfo->sSocket = sClientSocket;pClientInfo->m_IO_type = IO_RECV;LockClientArray();m_ClientArray.Add(pClientInfo);int nIndexInserted = m_ClientListBox.AddString(pClientInfo->GetShowText());m_ClientListBox.SetItemData(nIndexInserted,pClientInfo->sSocket);UnLockClientArray();if(bDelete)delete saClient;return pClientInfo; }void CServerDlg::OnSocketDisconnect(SOCKET aClientSocket) {LockClientArray();for(int i = 0;i<m_ClientArray.GetCount();i++){CClientInfo * pClientInfo = m_ClientArray.GetAt(i);if(pClientInfo->sSocket == aClientSocket){m_ClientListBox.DeleteString(m_ClientListBox.FindString(0,pClientInfo->GetShowText()));delete pClientInfo;m_ClientArray.RemoveAt(i);break;}}UnLockClientArray(); }BOOL CServerDlg::PostAccept(SOCKET sListenSocket) { // SOCKET sClientSocket = WSASocket(AF_INET, // SOCK_STREAM, // IPPROTO_TCP, // NULL,0,WSA_FLAG_OVERLAPPED); // char szBuf[256] = {0}; // DWORD dwByteReceived = 0; // OVERLAPPED ov; // memset(&ov,0,sizeof(ov)); // AcceptEx(sListenSocket,sClientSocket,szBuf,0,sizeof(sockaddr_in) + 16,sizeof(sockaddr_in) + 16,&dwByteReceived,&ov);OutputDebugStringA("PostAccept!\n");CClientInfo * pClientInfo = new CClientInfo;SOCKET sClientSocket = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,0,WSA_FLAG_OVERLAPPED);pClientInfo->sSocket = sListenSocket;pClientInfo->m_IO_type = IO_ACCEPT;pClientInfo->sAcceptSocket = sClientSocket;DWORD dwByteRecieved = 0;int nRet = AcceptEx(pClientInfo->sSocket,pClientInfo->sAcceptSocket,pClientInfo->m_szBuf,0,sizeof(sockaddr_in) + 16,sizeof(sockaddr_in) + 16,&dwByteRecieved,&pClientInfo->m_ol);if(nRet || ::WSAGetLastError() == ERROR_IO_PENDING){LockClientArray();m_ClientArray.Add(pClientInfo);UnLockClientArray();return TRUE;}else{AfxMessageBox(_T("出錯(cuò)非常嚴(yán)重!PostAccept"));return FALSE;}}BOOL CServerDlg::PostAccept(CClientInfo * pClientInfo) { OutputDebugStringA("PostAccept!\n");SOCKET sClientSocket = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,0,WSA_FLAG_OVERLAPPED);pClientInfo->m_IO_type = IO_ACCEPT;pClientInfo->sAcceptSocket = sClientSocket;DWORD dwByteRecieved = 0;int nRet = AcceptEx(pClientInfo->sSocket,pClientInfo->sAcceptSocket,pClientInfo->m_szBuf,0,sizeof(sockaddr_in) + 16,sizeof(sockaddr_in) + 16,&dwByteRecieved,&pClientInfo->m_ol);if(nRet || ::WSAGetLastError() == ERROR_IO_PENDING){return TRUE;}else{AfxMessageBox(_T("出錯(cuò)非常嚴(yán)重!PostAccept")); delete pClientInfo;return FALSE;} }void CServerDlg::PostRecv(CClientInfo * pClientInfo) {OutputDebugStringA("PostRecv!\n");WSABUF pBuf;pBuf.buf = pClientInfo->m_szBuf;pBuf.len = 256;DWORD cbRecv = 0;DWORD dwFlag = 0;int nRet = WSARecv(pClientInfo->sSocket,&pBuf,1,&cbRecv,&dwFlag,&pClientInfo->m_ol,NULL);if(nRet != 0){int nError = WSAGetLastError();}else{m_RecvMsgListBox.AddString((LPCTSTR)pBuf.buf);} } UINT AFX_CDECL AcceptThreadProc(LPVOID p) {CServerDlg * pThis = (CServerDlg*)p;while(true){sockaddr_in saClient = {0};int nClientSocketLen = sizeof(saClient);SOCKET sClientSocket = accept(pThis->m_ServerSocket,(sockaddr *)&saClient,&nClientSocketLen);CClientInfo * pClientInfo = pThis->OnSocketConnected(sClientSocket,&saClient);pThis->PostRecv(pClientInfo);Sleep(500);}return 0; }UINT AFX_CDECL WorkThreadProc(LPVOID p) {CServerDlg * pThis = (CServerDlg*)p;while (true){pThis->LockClientArray();int nClientCount = pThis->m_ClientArray.GetCount();WSAEVENT * pEvent = NULL;if(nClientCount > 0){pEvent = new WSAEVENT[nClientCount];for(int i = 0;i < nClientCount;i++)pEvent[i] = pThis->m_ClientArray.GetAt(i)->m_ol.hEvent;}pThis->UnLockClientArray();if(pEvent == NULL){Sleep(1000);continue;}DWORD dwWaitRet = ::WaitForMultipleObjects(nClientCount,pEvent,FALSE,10000);if(dwWaitRet == WAIT_FAILED){}else if(dwWaitRet == WAIT_TIMEOUT){}else{pThis->LockClientArray();CClientInfo * pClientInfo = pThis->m_ClientArray.GetAt(dwWaitRet - WAIT_OBJECT_0);WSAResetEvent(pClientInfo->m_ol.hEvent);char szDbg[256] = {0};sprintf_s(szDbg,"OverLapped:Internal:0x%x,InternalHigh:%d,Offset:%d,OffsetHigh:%d\n",pClientInfo->m_ol.Internal,pClientInfo->m_ol.InternalHigh,//發(fā)了多少字節(jié)pClientInfo->m_ol.Offset,pClientInfo->m_ol.OffsetHigh);OutputDebugStringA(szDbg);switch(pClientInfo->m_IO_type){case IO_RECV:if(pClientInfo->m_ol.InternalHigh == 0){//斷開連接 pThis->OnSocketDisconnect(pClientInfo->sSocket);}else{pClientInfo->m_szBuf[pClientInfo->m_ol.InternalHigh] = 0;pThis->m_RecvMsgListBox.AddString((LPCTSTR)pClientInfo->m_szBuf);pThis->PostRecv(pClientInfo); }break;case IO_ACCEPT:setsockopt(pClientInfo->sAcceptSocket,SOL_SOCKET,SO_UPDATE_ACCEPT_CONTEXT,(char*)&pClientInfo->sAcceptSocket,sizeof(pClientInfo->sAcceptSocket));CClientInfo * pNewClientInfo = pThis->OnSocketConnected(pClientInfo->sAcceptSocket,NULL);pThis->PostRecv(pNewClientInfo);pThis->PostAccept(pClientInfo);break;}pThis->UnLockClientArray();}delete [] pEvent;} }void CServerDlg::OnBnClickedButton1() {//啟動(dòng)服務(wù)端int nPort = GetDlgItemInt(IDC_EDIT_PORT);// TODO: 在此添加控件通知處理程序代碼m_ServerSocket = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,0,WSA_FLAG_OVERLAPPED);if(m_ServerSocket == INVALID_SOCKET){AfxMessageBox(_T("創(chuàng)建套接字失敗"));return ;}sockaddr_in saServer;saServer.sin_family = AF_INET; //地址家族 saServer.sin_port = htons(nPort); //注意轉(zhuǎn)化為網(wǎng)絡(luò)節(jié)序 saServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); if(SOCKET_ERROR == bind(m_ServerSocket,(SOCKADDR *)&saServer,sizeof(saServer))){AfxMessageBox(_T("綁定失敗"));return ;}if(SOCKET_ERROR == listen(m_ServerSocket,SOMAXCONN)){AfxMessageBox(_T("監(jiān)聽失敗啊"));return ;}//AfxBeginThread(AcceptThreadProc,this); PostAccept(m_ServerSocket);AfxBeginThread(WorkThreadProc,this);GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE); }void CServerDlg::InitSocket() {WSADATA wsaData = {0};if(0 != WSAStartup(MAKEWORD(2,2),&wsaData)){AfxMessageBox(_T("socket 初始化失敗"));return ;} }void CServerDlg::OnBnClickedButton3() {// TODO: 在此添加控件通知處理程序代碼if(m_ClientListBox.GetSelCount() <= 0){AfxMessageBox(_T("請(qǐng)選中右邊的客戶端進(jìn)行發(fā)送"));return ;}CString strSend;GetDlgItemText(IDC_EDIT2,strSend);for(int i = 0;i < m_ClientListBox.GetCount();i++){if(m_ClientListBox.GetSel(i) > 0){SOCKET aClientSocket = m_ClientListBox.GetItemData(i);if( SOCKET_ERROR == send(aClientSocket,(const char * )strSend.GetBuffer(),strSend.GetLength() * sizeof(TCHAR),0)){int nError = ::WSAGetLastError();CString strError;strError.Format(_T("send 失敗%d"),nError);AfxMessageBox(strError);}}} } 出處:http://www.cnblogs.com/zhangdongsheng/ 作者:張東升 QQ:290387340

總結(jié)

以上是生活随笔為你收集整理的Socket重叠IO的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。