手机
当前位置:查字典教程网 >编程开发 >C语言 >C++之WSAAsyncSelect模型实例
C++之WSAAsyncSelect模型实例
摘要:本文实例讲述了C++中WSAAsyncSelect模型的用法。分享给大家供大家参考。具体实现方法如下:TCPServer.cpp源文件如下:...

本文实例讲述了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)+"rn");

}

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模型实例】相关文章:

C++中的单例模式介绍

C++ 字符串的反转五种方法实例

C++流操作之fstream用法介绍

解析取模运算% 和位与运算& 之间的关系详解

ShellExecute函数用法的实例代码

C语言可变参数函数详解示例

浅析C和C++函数的相互引用

基于C语言sprintf函数的深入理解

从汇编看c++的默认析构函数的使用详解

解析VC中预编译头文件的深入分析

精品推荐
分类导航