C++中WSAAsyncSelect模型的用法例程
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                C++中WSAAsyncSelect模型的用法例程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                
                            
                            
                            
 
#include "resource.h"?
?
#define WM_SOCKET WM_USER+1?
?
CMyApp theApp;?
?
BOOL CMyApp::InitInstance()?
{?
??? //初始化套接字?
??? WSADATA wsaData;?
??? WORD wVersionRequested = MAKEWORD(2,0);?
??? ::WSAStartup(wVersionRequested, &wsaData);?
??? //顯示對話框?
??? CMainDialog dlg;?
??? m_pMainWnd = &dlg;?
??? dlg.DoModal();?
??? //釋放套接字?
??? ::WSACleanup();?
??? return FALSE;?
}?
?
//CMainDialog?
CMainDialog::CMainDialog(CWnd* pParentWnd):CDialog(IDD_MAINDIALOG,pParentWnd)?
{?
?
}?
BEGIN_MESSAGE_MAP(CMainDialog, CDialog)?
ON_BN_CLICKED(IDC_START, OnStart)?
ON_BN_CLICKED(IDC_CLEAR, OnClear)?
ON_MESSAGE(WM_SOCKET, OnSocket)?
END_MESSAGE_MAP()?
?
void CMainDialog::OnCancel()?
{?
??? this->CloseAllSocket();?
??? CDialog::OnCancel();?
}?
?
BOOL CMainDialog::OnInitDialog()?
{?
??? CDialog::OnInitDialog();?
?
??? //設置圖標?
??? SetIcon(theApp.LoadIconA(IDI_MAIN), FALSE);?
?
??? //創建狀態欄并設置其屬性?
??? m_bar.Create(WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP, CRect(0,0,0,0), this, 101);?
??? m_bar.SetBkColor(RGB(0xa6, 0xca, 0xfa));?
??? int arWidth[]={200,-1};?
??? m_bar.SetParts(2, arWidth);?
??? m_bar.SetText("windows程序設計", 1, 0);?
??? m_bar.SetText("空閑", 0, 0);?
??? //關聯列表控件?
??? m_listInfo.SubclassDlgItem(IDC_LIST, this);?
?
??? //初始化套接字和連接列表?
??? m_socket = INVALID_SOCKET;?
??? m_nClient = 0;?
?
??? //取得本機IP,在狀態欄中顯示?
??? char szHostName[MAX_PATH] = {0};?
??? ::gethostname(szHostName, MAX_PATH);?
??? hostent *pHost = gethostbyname(szHostName);?
??? if (pHost != NULL)?
??? {?
??????? CString strIP;?
??????? in_addr* addr = (in_addr*)*pHost->h_addr_list;?
??????? strIP.Format("本機IP:%s",inet_ntoa(addr[0]));?
??????? m_bar.SetText(strIP, 0, 0);?
??? }?
??? return TRUE;?
}?
?
BOOL CMainDialog::CreateAndListen(int nPort)?
{?
??? if (m_socket == INVALID_SOCKET)?
??? {?
??????? ::closesocket(m_socket);?
??? }?
??? //創建套接字?
??? m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);?
??? if (m_socket == INVALID_SOCKET)?
??? {?
??????? return FALSE;?
??? }?
??? //綁定端口?
??? sockaddr_in sin;?
??? sin.sin_family = AF_INET;?
??? sin.sin_port = htons(nPort);?
??? //sin.sin_addr.S_un.S_addr = INADDR_ANY;?
??? sin.sin_addr.s_addr = INADDR_ANY;?
??? int nErr = GetLastError();?
??? if (::bind(m_socket, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR)?
??? {?
??????? nErr = GetLastError();?
??????? return FALSE;?
??? }?
??? ::WSAAsyncSelect(m_socket, m_hWnd, WM_SOCKET, FD_ACCEPT|FD_CLOSE|FD_READ);?
?
??? //進入監聽模式?
??? ::listen(m_socket, 5);?
?
??? return TRUE;?
}?
?
BOOL CMainDialog::AddClient(SOCKET s)?
{?
?????
??? if (m_nClient < MAX_SOCKET)?
??? {?
??????? m_arClient[m_nClient++] = s;?
??????? return TRUE;?
??? }?
??? return FALSE;?
?????
}?
?
void CMainDialog::RemoveClient(SOCKET s)?
{?
??? BOOL bFound = FALSE;?
??? int i;?
??? for (i=0;i<m_nClient;i++)?
??? {?
??????? if (m_arClient[i] == s)?
??????? {?
??????????? bFound = TRUE;?
??????????? break;?
??????? }?
??? }?
?
??? //找到?
??? if (bFound)?
??? {?
??????? m_nClient--;?
??????? for (int j=i;j<m_nClient;j++)?
??????? {?
??????????? m_arClient[j] = m_arClient[j+1];?
??????? }?
??? }?
}?
void CMainDialog::CloseAllSocket()?
{?
??? if (m_socket != INVALID_SOCKET)?
??? {?
??????? ::closesocket(m_socket);?
??????? m_socket = INVALID_SOCKET;?
??? }?
??? for (int i=0;i<m_nClient;i++)?
??? {?
??????? ::closesocket(m_arClient[i]);?
??? }?
??? m_nClient = 0;?
}?
?
void CMainDialog::OnStart()?
{?
??? if (m_socket == INVALID_SOCKET) //開啟服務?
??? {?
??????? CString strPort;?
??????? GetDlgItem(IDC_PORT)->GetWindowText(strPort);?
??????? int nPort = atoi(strPort);?
??????? if (nPort < 1 || nPort >65535)?
??????? {?
??????????? MessageBox("port error");?
??????????? return;?
??????? }?
??????? //創建套接字?
??????? if (!this->CreateAndListen(nPort))?
??????? {?
??????????? MessageBox("create socket error");?
??????????? return;?
??????? }?
??????? //設置控件狀態?
??????? GetDlgItem(IDC_START)->SetWindowTextA("停止服務");?
??????? m_bar.SetText("正在監聽...", 0, 0);?
??????? GetDlgItem(IDC_PORT)->EnableWindow(FALSE);?
??? }?
??? else //關閉服務?
??? {?
??????? CloseAllSocket();?
??????? GetDlgItem(IDC_START)->SetWindowTextA("開啟服務");?
??????? m_bar.SetText("空閑", 0, 0);?
??????? GetDlgItem(IDC_PORT)->EnableWindow(TRUE);?
??? }?
??? return ;?
}?
void CMainDialog::OnClear()?
{?
??? m_listInfo.ResetContent();?
??? return ;?
}?
?
long CMainDialog::OnSocket(WPARAM wParam, LPARAM lParam)?
{?
??? //得到句柄??
??? SOCKET s = wParam;?
??? //查看是否出錯?
??? if (WSAGETSELECTERROR(lParam))?
??? {?
??????? RemoveClient(s);?
??????? ::closesocket(s);?
??????? return 0;?
??? }?
??? //處理發生的事件?
??? switch (WSAGETSELECTEVENT(lParam))?
??? {?
??? case FD_ACCEPT: //監聽到有套接字中有連接進入?
??????? {?
??????????? MessageBox("server:accept");?
??????????? if (m_nClient < MAX_SOCKET)?
??????????? {?
??????????????? SOCKET client = ::accept(s, NULL, NULL);?
??????????????? this->AddClient(client);?
??????????? }?
??????????? else?
??????????? {?
??????????????? MessageBox("too many connection");?
??????????? }?
??????? }?
??????? break;?
??? case FD_CLOSE:?
??????? {?
??????????? MessageBox("server:close");?
??????????? RemoveClient(s);?
??????????? closesocket(s);?
??????? }?
??????? break;?
??? case FD_READ: //接收到對方發來的數據包?
??????? {?
??????????? MessageBox("server:read");?
??????????? //得到對方的地址?
??????????? sockaddr_in sockAddr;?
??????????? memset(&sockAddr, 0, sizeof(sockAddr));?
??????????? int nSockAddrLength = sizeof(sockAddr);?
??????????? ::getpeername(s, (sockaddr*)&sockAddr, &nSockAddrLength);?
?
??????????? int nPeerPort = ntohs(sockAddr.sin_port);?
??????????? CString strIP = inet_ntoa(sockAddr.sin_addr);? // strIP?
?
??????????? //獲得主機名稱?
??????????? DWORD dwIP = ::inet_addr(strIP);?
??????????? hostent* pHost = ::gethostbyaddr((LPSTR)&dwIP, 4, AF_INET);?
??????????? char szHostName[256]={0};?
??????????? strncpy(szHostName, pHost->h_name, 256);?
?
??????????? //得到網絡數據?
??????????? char szContent[1024]={0};?
??????????? ::recv(s, szContent, 1024, 0);?
?
??????????? //顯示?
??????????? CString strItem = CString(szHostName) + "[" + strIP + "]:" + CString(szContent);?
??????????? m_listInfo.InsertString(0, strItem);?
??????? }?
??????? break;?
??? }?
??? return 0;?
}
#include <afxext.h>? //CStatusBar?
#include <WinSock2.h>?
#include <afxcmn.h>?
?
#pragma comment(lib, "WS2_32.lib")?
#define? MAX_SOCKET 56 //最大客戶量?
?
class CMyApp:public? CWinApp?
{?
public:?
??? BOOL InitInstance();?
};?
?
//CMainDialog?
class CMainDialog:public CDialog?
{?
public:?
??? CMainDialog(CWnd* pParentWnd=NULL);?
?
protected:?
??? virtual BOOL OnInitDialog();?
??? virtual void OnCancel();?
??? //開啟或停止服務?
??? afx_msg void OnStart();?
??? afx_msg void OnClear();?
??? afx_msg long OnSocket(WPARAM wParam, LPARAM lParam);?
?
??? BOOL CreateAndListen(int nPort);?
?
??? //向客戶連接列表中加一個客戶?
??? BOOL AddClient(SOCKET s);?
??? //從客戶連接列表中移除一個客戶?
??? void RemoveClient(SOCKET s);?
??? //關閉所有連接?
??? void CloseAllSocket();?
?
protected:?
??? SOCKET m_socket;?
??? //兩個子窗口控件?
??? CListBox m_listInfo;?
??? CStatusBarCtrl m_bar;?
?
??? //客戶連接列表?
??? SOCKET m_arClient[MAX_SOCKET]; //套接字列表?
??? int m_nClient; //上述數組的大小?
?
??? DECLARE_MESSAGE_MAP()?
};
#include "resource.h"?
?
#define WM_SOCKET WM_USER+1?
?
CMyApp theApp;?
?
BOOL CMyApp::InitInstance()?
{?
??? //初始化套接字?
??? WSADATA wsaData;?
??? WORD wVersionRequested = MAKEWORD(2,0);?
??? ::WSAStartup(wVersionRequested, &wsaData);?
??? //顯示對話框?
??? CMainDialog dlg;?
??? m_pMainWnd = &dlg;?
??? dlg.DoModal();?
??? //釋放套接字?
??? ::WSACleanup();?
??? return FALSE;?
}?
?
//CMainDialog?
CMainDialog::CMainDialog(CWnd* pParentWnd):CDialog(IDD_MAINDIALOG,pParentWnd)?
{?
?
}?
BEGIN_MESSAGE_MAP(CMainDialog, CDialog)?
??? ON_BN_CLICKED(IDC_CONNECT, OnConnect)?
??? ON_BN_CLICKED(IDC_SEND, OnSend)?
??? ON_MESSAGE(WM_SOCKET, OnSocket)?
END_MESSAGE_MAP()?
?
void CMainDialog::OnCancel()?
{?
?????
??? CDialog::OnCancel();?
}?
?
BOOL CMainDialog::OnInitDialog()?
{?
??? CDialog::OnInitDialog();?
?
??? //設置圖標?
??? SetIcon(theApp.LoadIconA(IDI_MAIN), FALSE);?
?
??? //關聯控件?
??? m_edit_text.SubclassDlgItem(IDC_EDIT_CONTENT, this);?
??? //狀態欄?
??? m_bar.Create(WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP, CRect(0, 0, 0,0), this, NULL);?
??? int nWidth[]={100,-1};?
??? m_bar.SetParts(2, nWidth);?
??? m_bar.SetText("windows程序設計", 1, 0);?
??? m_bar.SetText("空閑", 0, 0);?
?
??? GetDlgItem(IDC_ADDR)->SetWindowTextA("192.168.19.143");?
??? GetDlgItem(IDC_PORT)->SetWindowTextA("9999");?
?
??? //?
??? m_socket = INVALID_SOCKET;?
?????
??? return TRUE;?
}?
void CMainDialog::AddStringToList(CString strText)?
{?
??? CString strContent;?
??? GetDlgItem(IDC_EDIT_CONTENT)->GetWindowText(strContent);?
??? GetDlgItem(IDC_EDIT_CONTENT)->SetWindowText(strContent+strText);?
?
}?
long CMainDialog::OnSocket(WPARAM wParam, LPARAM lParam)?
{?
??? SOCKET? s = wParam;?
??? if (WSAGETSELECTERROR(lParam))?
??? {?
??????? ::closesocket(m_socket);?
??????? m_socket = INVALID_SOCKET;?
??????? return 0;?
??? }?
??? switch (WSAGETSELECTEVENT(lParam))?
??? {?
??? case FD_READ:?
??????? {?
??????????? MessageBox("client:read");?
??????????? char szText[1024]={0};?
??????????? ::recv(s, szText, 1024, 0);?
??????????? AddStringToList(CString(szText)+"\r\n");?
??????? }?
??????? break;?
??? case FD_CONNECT:?
??????? {?
??????????? MessageBox("client:connect");?
??????????? GetDlgItem(IDC_CONNECT)->SetWindowTextA("斷開連接");?
??????????? GetDlgItem(IDC_ADDR)->EnableWindow(FALSE);?
??????????? GetDlgItem(IDC_PORT)->EnableWindow(FALSE);?
??????????? GetDlgItem(IDC_TEXT)->EnableWindow(TRUE);?
??????????? GetDlgItem(IDC_SEND)->EnableWindow(TRUE);?
??????????? m_bar.SetText("已經連接到服務器", 0, 0);?
??????? }?
??????? break;?
??? case FD_CLOSE:?
??????? {?
??????????? MessageBox("client:close");?
??????????? OnConnect();?
??????? }?
??????? break;?
??? }?
??? return 0;?
}?
?
BOOL CMainDialog::Connect(LPCTSTR pszRemoteAddr, u_short nPort)?
{?
??? //創建套接字?
??? m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);?
??? if (INVALID_SOCKET == m_socket)?
??? {?
??????? return FALSE;?
??? }?
??? ::WSAAsyncSelect(m_socket, m_hWnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CONNECT|FD_CLOSE);?
?
??? ULONG uAddr = ::inet_addr(pszRemoteAddr);?
??? if (uAddr == INADDR_NONE)?
??? {?
??????? //不是IP地址,就認為是主機名稱?
??????? //從主機名得到IP?
??????? hostent* pHost = ::gethostbyname(pszRemoteAddr);?
??????? if (pHost == NULL)?
??????? {?
??????????? ::closesocket(m_socket);?
??????????? m_socket = INVALID_SOCKET;?
??????????? return FALSE;?
??????? }?
??????? uAddr = ((struct in_addr*)*(pHost->h_addr_list))->s_addr;?
??? }?
?
??? //填寫服務器信息?
??? sockaddr_in remote;?
??? remote.sin_family = AF_INET;?
??? remote.sin_addr.S_un.S_addr = uAddr;?
??? remote.sin_port = ::htons(nPort);?
??? //連接?
??? ::connect(m_socket, (sockaddr*)&remote, sizeof(sockaddr));?
??? return TRUE;?
}?
?
void CMainDialog::OnConnect()?
{?
??? if (INVALID_SOCKET == m_socket) //連接服務器?
??? {?
??????? CString strAddr;?
??????? GetDlgItem(IDC_ADDR)->GetWindowText(strAddr);?
??????? if (strAddr.IsEmpty())?
??????? {?
??????????? MessageBox("the servers IP is empty");?
??????????? return;?
??????? }?
??????? CString strPort;?
??????? GetDlgItem(IDC_PORT)->GetWindowTextA(strPort);?
??????? int nPort = atoi(strPort);?
??????? if (nPort < 1 || nPort > 65535)?
??????? {?
??????????? MessageBox("port error");?
??????????? return;?
??????? }?
??????? if (Connect(strAddr, nPort) == FALSE)?
??????? {?
??????????? MessageBox("connect to servers error...");?
??????????? return;?
??????? }?
??????? //設置用戶界面?
??????? GetDlgItem(IDC_CONNECT)->SetWindowText("取消");?
??????? m_bar.SetText("正在連接..", 0, 0);?
?????????
??? }?
??? else //斷開服務器?
??? {?
??????? ::closesocket(m_socket);?
??????? m_socket = INVALID_SOCKET;?
??????? //設置用戶界面?
??????? GetDlgItem(IDC_CONNECT)->SetWindowTextA("連接服務器");?
??????? m_bar.SetText("空閑", 0, 0);?
??????? GetDlgItem(IDC_ADDR)->EnableWindow(TRUE);?
??????? GetDlgItem(IDC_PORT)->EnableWindow(TRUE);?
??????? GetDlgItem(IDC_SEND)->EnableWindow(FALSE);?
??????? GetDlgItem(IDC_TEXT)->EnableWindow(FALSE);?
??? }?
?????
??? //this->Connect(szAddr, )?
}?
void CMainDialog::OnSend()?
{?
??? CString strSendContent;?
??? GetDlgItem(IDC_TEXT)->GetWindowTextA(strSendContent);?
??? ::send(m_socket, strSendContent, strSendContent.GetLength(), 0);?
??? GetDlgItem(IDC_TEXT)->SetWindowTextA("");?
}
#include <afxext.h>? //CStatusBar?
#include <WinSock2.h>?
#include <afxcmn.h>?
?
#pragma comment(lib, "WS2_32.lib")?
#define? MAX_SOCKET 56 //最大客戶量?
?
class CMyApp:public? CWinApp?
{?
public:?
??? BOOL InitInstance();?
};?
?
?
//CMainDialog?
class CMainDialog:public CDialog?
{?
public:?
??? CMainDialog(CWnd* pParentWnd=NULL);?
?
protected:?
??? virtual BOOL OnInitDialog();?
??? virtual void OnCancel();?
??? 開啟或停止服務?
??? //afx_msg void OnStart();?
??? afx_msg void OnSend();?
??? afx_msg long OnSocket(WPARAM wParam, LPARAM lParam);?
??? void OnConnect();?
?
??? BOOL Connect(LPCTSTR pszRemoteAddr, u_short nPort);?
??? SOCKET m_socket;?
?
??? // 控件?
??? CStatusBarCtrl m_bar;?
??? CEdit m_edit_text;?
?
??? void AddStringToList(CString strText);?
??? //BOOL CreateAndListen(int nPort);?
?
??? 向客戶連接列表中加一個客戶?
??? //BOOL AddClient(SOCKET s);?
??? 從客戶連接列表中移除一個客戶?
??? //void RemoveClient(SOCKET s);?
??? 關閉所有連接?
??? //void CloseAllSocket();?
?
?
??? DECLARE_MESSAGE_MAP()?
};
                        
                        
                        本文實例講述了C++中WSAAsyncSelect模型的用法。分享給大家供大家參考。具體實現方法如下:
TCPServer.cpp源文件如下:
復制代碼 代碼如下: #include "TCPServer.h"?#include "resource.h"?
?
#define WM_SOCKET WM_USER+1?
?
CMyApp theApp;?
?
BOOL CMyApp::InitInstance()?
{?
??? //初始化套接字?
??? WSADATA wsaData;?
??? WORD wVersionRequested = MAKEWORD(2,0);?
??? ::WSAStartup(wVersionRequested, &wsaData);?
??? //顯示對話框?
??? CMainDialog dlg;?
??? m_pMainWnd = &dlg;?
??? dlg.DoModal();?
??? //釋放套接字?
??? ::WSACleanup();?
??? return FALSE;?
}?
?
//CMainDialog?
CMainDialog::CMainDialog(CWnd* pParentWnd):CDialog(IDD_MAINDIALOG,pParentWnd)?
{?
?
}?
BEGIN_MESSAGE_MAP(CMainDialog, CDialog)?
ON_BN_CLICKED(IDC_START, OnStart)?
ON_BN_CLICKED(IDC_CLEAR, OnClear)?
ON_MESSAGE(WM_SOCKET, OnSocket)?
END_MESSAGE_MAP()?
?
void CMainDialog::OnCancel()?
{?
??? this->CloseAllSocket();?
??? CDialog::OnCancel();?
}?
?
BOOL CMainDialog::OnInitDialog()?
{?
??? CDialog::OnInitDialog();?
?
??? //設置圖標?
??? SetIcon(theApp.LoadIconA(IDI_MAIN), FALSE);?
?
??? //創建狀態欄并設置其屬性?
??? m_bar.Create(WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP, CRect(0,0,0,0), this, 101);?
??? m_bar.SetBkColor(RGB(0xa6, 0xca, 0xfa));?
??? int arWidth[]={200,-1};?
??? m_bar.SetParts(2, arWidth);?
??? m_bar.SetText("windows程序設計", 1, 0);?
??? m_bar.SetText("空閑", 0, 0);?
??? //關聯列表控件?
??? m_listInfo.SubclassDlgItem(IDC_LIST, this);?
?
??? //初始化套接字和連接列表?
??? m_socket = INVALID_SOCKET;?
??? m_nClient = 0;?
?
??? //取得本機IP,在狀態欄中顯示?
??? char szHostName[MAX_PATH] = {0};?
??? ::gethostname(szHostName, MAX_PATH);?
??? hostent *pHost = gethostbyname(szHostName);?
??? if (pHost != NULL)?
??? {?
??????? CString strIP;?
??????? in_addr* addr = (in_addr*)*pHost->h_addr_list;?
??????? strIP.Format("本機IP:%s",inet_ntoa(addr[0]));?
??????? m_bar.SetText(strIP, 0, 0);?
??? }?
??? return TRUE;?
}?
?
BOOL CMainDialog::CreateAndListen(int nPort)?
{?
??? if (m_socket == INVALID_SOCKET)?
??? {?
??????? ::closesocket(m_socket);?
??? }?
??? //創建套接字?
??? m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);?
??? if (m_socket == INVALID_SOCKET)?
??? {?
??????? return FALSE;?
??? }?
??? //綁定端口?
??? sockaddr_in sin;?
??? sin.sin_family = AF_INET;?
??? sin.sin_port = htons(nPort);?
??? //sin.sin_addr.S_un.S_addr = INADDR_ANY;?
??? sin.sin_addr.s_addr = INADDR_ANY;?
??? int nErr = GetLastError();?
??? if (::bind(m_socket, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR)?
??? {?
??????? nErr = GetLastError();?
??????? return FALSE;?
??? }?
??? ::WSAAsyncSelect(m_socket, m_hWnd, WM_SOCKET, FD_ACCEPT|FD_CLOSE|FD_READ);?
?
??? //進入監聽模式?
??? ::listen(m_socket, 5);?
?
??? return TRUE;?
}?
?
BOOL CMainDialog::AddClient(SOCKET s)?
{?
?????
??? if (m_nClient < MAX_SOCKET)?
??? {?
??????? m_arClient[m_nClient++] = s;?
??????? return TRUE;?
??? }?
??? return FALSE;?
?????
}?
?
void CMainDialog::RemoveClient(SOCKET s)?
{?
??? BOOL bFound = FALSE;?
??? int i;?
??? for (i=0;i<m_nClient;i++)?
??? {?
??????? if (m_arClient[i] == s)?
??????? {?
??????????? bFound = TRUE;?
??????????? break;?
??????? }?
??? }?
?
??? //找到?
??? if (bFound)?
??? {?
??????? m_nClient--;?
??????? for (int j=i;j<m_nClient;j++)?
??????? {?
??????????? m_arClient[j] = m_arClient[j+1];?
??????? }?
??? }?
}?
void CMainDialog::CloseAllSocket()?
{?
??? if (m_socket != INVALID_SOCKET)?
??? {?
??????? ::closesocket(m_socket);?
??????? m_socket = INVALID_SOCKET;?
??? }?
??? for (int i=0;i<m_nClient;i++)?
??? {?
??????? ::closesocket(m_arClient[i]);?
??? }?
??? m_nClient = 0;?
}?
?
void CMainDialog::OnStart()?
{?
??? if (m_socket == INVALID_SOCKET) //開啟服務?
??? {?
??????? CString strPort;?
??????? GetDlgItem(IDC_PORT)->GetWindowText(strPort);?
??????? int nPort = atoi(strPort);?
??????? if (nPort < 1 || nPort >65535)?
??????? {?
??????????? MessageBox("port error");?
??????????? return;?
??????? }?
??????? //創建套接字?
??????? if (!this->CreateAndListen(nPort))?
??????? {?
??????????? MessageBox("create socket error");?
??????????? return;?
??????? }?
??????? //設置控件狀態?
??????? GetDlgItem(IDC_START)->SetWindowTextA("停止服務");?
??????? m_bar.SetText("正在監聽...", 0, 0);?
??????? GetDlgItem(IDC_PORT)->EnableWindow(FALSE);?
??? }?
??? else //關閉服務?
??? {?
??????? CloseAllSocket();?
??????? GetDlgItem(IDC_START)->SetWindowTextA("開啟服務");?
??????? m_bar.SetText("空閑", 0, 0);?
??????? GetDlgItem(IDC_PORT)->EnableWindow(TRUE);?
??? }?
??? return ;?
}?
void CMainDialog::OnClear()?
{?
??? m_listInfo.ResetContent();?
??? return ;?
}?
?
long CMainDialog::OnSocket(WPARAM wParam, LPARAM lParam)?
{?
??? //得到句柄??
??? SOCKET s = wParam;?
??? //查看是否出錯?
??? if (WSAGETSELECTERROR(lParam))?
??? {?
??????? RemoveClient(s);?
??????? ::closesocket(s);?
??????? return 0;?
??? }?
??? //處理發生的事件?
??? switch (WSAGETSELECTEVENT(lParam))?
??? {?
??? case FD_ACCEPT: //監聽到有套接字中有連接進入?
??????? {?
??????????? MessageBox("server:accept");?
??????????? if (m_nClient < MAX_SOCKET)?
??????????? {?
??????????????? SOCKET client = ::accept(s, NULL, NULL);?
??????????????? this->AddClient(client);?
??????????? }?
??????????? else?
??????????? {?
??????????????? MessageBox("too many connection");?
??????????? }?
??????? }?
??????? break;?
??? case FD_CLOSE:?
??????? {?
??????????? MessageBox("server:close");?
??????????? RemoveClient(s);?
??????????? closesocket(s);?
??????? }?
??????? break;?
??? case FD_READ: //接收到對方發來的數據包?
??????? {?
??????????? MessageBox("server:read");?
??????????? //得到對方的地址?
??????????? sockaddr_in sockAddr;?
??????????? memset(&sockAddr, 0, sizeof(sockAddr));?
??????????? int nSockAddrLength = sizeof(sockAddr);?
??????????? ::getpeername(s, (sockaddr*)&sockAddr, &nSockAddrLength);?
?
??????????? int nPeerPort = ntohs(sockAddr.sin_port);?
??????????? CString strIP = inet_ntoa(sockAddr.sin_addr);? // strIP?
?
??????????? //獲得主機名稱?
??????????? DWORD dwIP = ::inet_addr(strIP);?
??????????? hostent* pHost = ::gethostbyaddr((LPSTR)&dwIP, 4, AF_INET);?
??????????? char szHostName[256]={0};?
??????????? strncpy(szHostName, pHost->h_name, 256);?
?
??????????? //得到網絡數據?
??????????? char szContent[1024]={0};?
??????????? ::recv(s, szContent, 1024, 0);?
?
??????????? //顯示?
??????????? CString strItem = CString(szHostName) + "[" + strIP + "]:" + CString(szContent);?
??????????? m_listInfo.InsertString(0, strItem);?
??????? }?
??????? break;?
??? }?
??? return 0;?
}
TCPServer.h頭文件如下:
復制代碼 代碼如下: #include <afxwin.h>?#include <afxext.h>? //CStatusBar?
#include <WinSock2.h>?
#include <afxcmn.h>?
?
#pragma comment(lib, "WS2_32.lib")?
#define? MAX_SOCKET 56 //最大客戶量?
?
class CMyApp:public? CWinApp?
{?
public:?
??? BOOL InitInstance();?
};?
?
//CMainDialog?
class CMainDialog:public CDialog?
{?
public:?
??? CMainDialog(CWnd* pParentWnd=NULL);?
?
protected:?
??? virtual BOOL OnInitDialog();?
??? virtual void OnCancel();?
??? //開啟或停止服務?
??? afx_msg void OnStart();?
??? afx_msg void OnClear();?
??? afx_msg long OnSocket(WPARAM wParam, LPARAM lParam);?
?
??? BOOL CreateAndListen(int nPort);?
?
??? //向客戶連接列表中加一個客戶?
??? BOOL AddClient(SOCKET s);?
??? //從客戶連接列表中移除一個客戶?
??? void RemoveClient(SOCKET s);?
??? //關閉所有連接?
??? void CloseAllSocket();?
?
protected:?
??? SOCKET m_socket;?
??? //兩個子窗口控件?
??? CListBox m_listInfo;?
??? CStatusBarCtrl m_bar;?
?
??? //客戶連接列表?
??? SOCKET m_arClient[MAX_SOCKET]; //套接字列表?
??? int m_nClient; //上述數組的大小?
?
??? DECLARE_MESSAGE_MAP()?
};
TCPClient.cpp源文件如下:
復制代碼 代碼如下: #include "TCPClient.h"?#include "resource.h"?
?
#define WM_SOCKET WM_USER+1?
?
CMyApp theApp;?
?
BOOL CMyApp::InitInstance()?
{?
??? //初始化套接字?
??? WSADATA wsaData;?
??? WORD wVersionRequested = MAKEWORD(2,0);?
??? ::WSAStartup(wVersionRequested, &wsaData);?
??? //顯示對話框?
??? CMainDialog dlg;?
??? m_pMainWnd = &dlg;?
??? dlg.DoModal();?
??? //釋放套接字?
??? ::WSACleanup();?
??? return FALSE;?
}?
?
//CMainDialog?
CMainDialog::CMainDialog(CWnd* pParentWnd):CDialog(IDD_MAINDIALOG,pParentWnd)?
{?
?
}?
BEGIN_MESSAGE_MAP(CMainDialog, CDialog)?
??? ON_BN_CLICKED(IDC_CONNECT, OnConnect)?
??? ON_BN_CLICKED(IDC_SEND, OnSend)?
??? ON_MESSAGE(WM_SOCKET, OnSocket)?
END_MESSAGE_MAP()?
?
void CMainDialog::OnCancel()?
{?
?????
??? CDialog::OnCancel();?
}?
?
BOOL CMainDialog::OnInitDialog()?
{?
??? CDialog::OnInitDialog();?
?
??? //設置圖標?
??? SetIcon(theApp.LoadIconA(IDI_MAIN), FALSE);?
?
??? //關聯控件?
??? m_edit_text.SubclassDlgItem(IDC_EDIT_CONTENT, this);?
??? //狀態欄?
??? m_bar.Create(WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP, CRect(0, 0, 0,0), this, NULL);?
??? int nWidth[]={100,-1};?
??? m_bar.SetParts(2, nWidth);?
??? m_bar.SetText("windows程序設計", 1, 0);?
??? m_bar.SetText("空閑", 0, 0);?
?
??? GetDlgItem(IDC_ADDR)->SetWindowTextA("192.168.19.143");?
??? GetDlgItem(IDC_PORT)->SetWindowTextA("9999");?
?
??? //?
??? m_socket = INVALID_SOCKET;?
?????
??? return TRUE;?
}?
void CMainDialog::AddStringToList(CString strText)?
{?
??? CString strContent;?
??? GetDlgItem(IDC_EDIT_CONTENT)->GetWindowText(strContent);?
??? GetDlgItem(IDC_EDIT_CONTENT)->SetWindowText(strContent+strText);?
?
}?
long CMainDialog::OnSocket(WPARAM wParam, LPARAM lParam)?
{?
??? SOCKET? s = wParam;?
??? if (WSAGETSELECTERROR(lParam))?
??? {?
??????? ::closesocket(m_socket);?
??????? m_socket = INVALID_SOCKET;?
??????? return 0;?
??? }?
??? switch (WSAGETSELECTEVENT(lParam))?
??? {?
??? case FD_READ:?
??????? {?
??????????? MessageBox("client:read");?
??????????? char szText[1024]={0};?
??????????? ::recv(s, szText, 1024, 0);?
??????????? AddStringToList(CString(szText)+"\r\n");?
??????? }?
??????? break;?
??? case FD_CONNECT:?
??????? {?
??????????? MessageBox("client:connect");?
??????????? GetDlgItem(IDC_CONNECT)->SetWindowTextA("斷開連接");?
??????????? GetDlgItem(IDC_ADDR)->EnableWindow(FALSE);?
??????????? GetDlgItem(IDC_PORT)->EnableWindow(FALSE);?
??????????? GetDlgItem(IDC_TEXT)->EnableWindow(TRUE);?
??????????? GetDlgItem(IDC_SEND)->EnableWindow(TRUE);?
??????????? m_bar.SetText("已經連接到服務器", 0, 0);?
??????? }?
??????? break;?
??? case FD_CLOSE:?
??????? {?
??????????? MessageBox("client:close");?
??????????? OnConnect();?
??????? }?
??????? break;?
??? }?
??? return 0;?
}?
?
BOOL CMainDialog::Connect(LPCTSTR pszRemoteAddr, u_short nPort)?
{?
??? //創建套接字?
??? m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);?
??? if (INVALID_SOCKET == m_socket)?
??? {?
??????? return FALSE;?
??? }?
??? ::WSAAsyncSelect(m_socket, m_hWnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CONNECT|FD_CLOSE);?
?
??? ULONG uAddr = ::inet_addr(pszRemoteAddr);?
??? if (uAddr == INADDR_NONE)?
??? {?
??????? //不是IP地址,就認為是主機名稱?
??????? //從主機名得到IP?
??????? hostent* pHost = ::gethostbyname(pszRemoteAddr);?
??????? if (pHost == NULL)?
??????? {?
??????????? ::closesocket(m_socket);?
??????????? m_socket = INVALID_SOCKET;?
??????????? return FALSE;?
??????? }?
??????? uAddr = ((struct in_addr*)*(pHost->h_addr_list))->s_addr;?
??? }?
?
??? //填寫服務器信息?
??? sockaddr_in remote;?
??? remote.sin_family = AF_INET;?
??? remote.sin_addr.S_un.S_addr = uAddr;?
??? remote.sin_port = ::htons(nPort);?
??? //連接?
??? ::connect(m_socket, (sockaddr*)&remote, sizeof(sockaddr));?
??? return TRUE;?
}?
?
void CMainDialog::OnConnect()?
{?
??? if (INVALID_SOCKET == m_socket) //連接服務器?
??? {?
??????? CString strAddr;?
??????? GetDlgItem(IDC_ADDR)->GetWindowText(strAddr);?
??????? if (strAddr.IsEmpty())?
??????? {?
??????????? MessageBox("the servers IP is empty");?
??????????? return;?
??????? }?
??????? CString strPort;?
??????? GetDlgItem(IDC_PORT)->GetWindowTextA(strPort);?
??????? int nPort = atoi(strPort);?
??????? if (nPort < 1 || nPort > 65535)?
??????? {?
??????????? MessageBox("port error");?
??????????? return;?
??????? }?
??????? if (Connect(strAddr, nPort) == FALSE)?
??????? {?
??????????? MessageBox("connect to servers error...");?
??????????? return;?
??????? }?
??????? //設置用戶界面?
??????? GetDlgItem(IDC_CONNECT)->SetWindowText("取消");?
??????? m_bar.SetText("正在連接..", 0, 0);?
?????????
??? }?
??? else //斷開服務器?
??? {?
??????? ::closesocket(m_socket);?
??????? m_socket = INVALID_SOCKET;?
??????? //設置用戶界面?
??????? GetDlgItem(IDC_CONNECT)->SetWindowTextA("連接服務器");?
??????? m_bar.SetText("空閑", 0, 0);?
??????? GetDlgItem(IDC_ADDR)->EnableWindow(TRUE);?
??????? GetDlgItem(IDC_PORT)->EnableWindow(TRUE);?
??????? GetDlgItem(IDC_SEND)->EnableWindow(FALSE);?
??????? GetDlgItem(IDC_TEXT)->EnableWindow(FALSE);?
??? }?
?????
??? //this->Connect(szAddr, )?
}?
void CMainDialog::OnSend()?
{?
??? CString strSendContent;?
??? GetDlgItem(IDC_TEXT)->GetWindowTextA(strSendContent);?
??? ::send(m_socket, strSendContent, strSendContent.GetLength(), 0);?
??? GetDlgItem(IDC_TEXT)->SetWindowTextA("");?
}
TCPClient.h頭文件如下:
復制代碼 代碼如下: #include <afxwin.h>?#include <afxext.h>? //CStatusBar?
#include <WinSock2.h>?
#include <afxcmn.h>?
?
#pragma comment(lib, "WS2_32.lib")?
#define? MAX_SOCKET 56 //最大客戶量?
?
class CMyApp:public? CWinApp?
{?
public:?
??? BOOL InitInstance();?
};?
?
?
//CMainDialog?
class CMainDialog:public CDialog?
{?
public:?
??? CMainDialog(CWnd* pParentWnd=NULL);?
?
protected:?
??? virtual BOOL OnInitDialog();?
??? virtual void OnCancel();?
??? 開啟或停止服務?
??? //afx_msg void OnStart();?
??? afx_msg void OnSend();?
??? afx_msg long OnSocket(WPARAM wParam, LPARAM lParam);?
??? void OnConnect();?
?
??? BOOL Connect(LPCTSTR pszRemoteAddr, u_short nPort);?
??? SOCKET m_socket;?
?
??? // 控件?
??? CStatusBarCtrl m_bar;?
??? CEdit m_edit_text;?
?
??? void AddStringToList(CString strText);?
??? //BOOL CreateAndListen(int nPort);?
?
??? 向客戶連接列表中加一個客戶?
??? //BOOL AddClient(SOCKET s);?
??? 從客戶連接列表中移除一個客戶?
??? //void RemoveClient(SOCKET s);?
??? 關閉所有連接?
??? //void CloseAllSocket();?
?
?
??? DECLARE_MESSAGE_MAP()?
};
希望本文所述對大家的C++程序設計有所幫助。
總結
以上是生活随笔為你收集整理的C++中WSAAsyncSelect模型的用法例程的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: h264的码率控制 JVT-G012
- 下一篇: Winsock属性 方法介绍
