C++之WSAAsyncSelect模型實(shí)例
更新時(shí)間:2014年10月20日 14:47:26 投稿:shichen2014
這篇文章主要介紹了C++的WSAAsyncSelect模型,實(shí)例講述了socket與Windows消息機(jī)制的用法,需要的朋友可以參考下
本文實(shí)例講述了C++中WSAAsyncSelect模型的用法。分享給大家供大家參考。具體實(shí)現(xiàn)方法如下:
TCPServer.cpp源文件如下:
復(fù)制代碼 代碼如下:
#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();
//設(shè)置圖標(biāo)
SetIcon(theApp.LoadIconA(IDI_MAIN), FALSE);
//創(chuàng)建狀態(tài)欄并設(shè)置其屬性
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程序設(shè)計(jì)", 1, 0);
m_bar.SetText("空閑", 0, 0);
//關(guān)聯(lián)列表控件
m_listInfo.SubclassDlgItem(IDC_LIST, this);
//初始化套接字和連接列表
m_socket = INVALID_SOCKET;
m_nClient = 0;
//取得本機(jī)IP,在狀態(tài)欄中顯示
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("本機(jī)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);
}
//創(chuàng)建套接字
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);
//進(jìn)入監(jiān)聽模式
::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) //開啟服務(wù)
{
CString strPort;
GetDlgItem(IDC_PORT)->GetWindowText(strPort);
int nPort = atoi(strPort);
if (nPort < 1 || nPort >65535)
{
MessageBox("port error");
return;
}
//創(chuàng)建套接字
if (!this->CreateAndListen(nPort))
{
MessageBox("create socket error");
return;
}
//設(shè)置控件狀態(tài)
GetDlgItem(IDC_START)->SetWindowTextA("停止服務(wù)");
m_bar.SetText("正在監(jiān)聽...", 0, 0);
GetDlgItem(IDC_PORT)->EnableWindow(FALSE);
}
else //關(guān)閉服務(wù)
{
CloseAllSocket();
GetDlgItem(IDC_START)->SetWindowTextA("開啟服務(wù)");
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;
//查看是否出錯(cuò)
if (WSAGETSELECTERROR(lParam))
{
RemoveClient(s);
::closesocket(s);
return 0;
}
//處理發(fā)生的事件
switch (WSAGETSELECTEVENT(lParam))
{
case FD_ACCEPT: //監(jiān)聽到有套接字中有連接進(jìn)入
{
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: //接收到對方發(fā)來的數(shù)據(jù)包
{
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
//獲得主機(jī)名稱
DWORD dwIP = ::inet_addr(strIP);
hostent* pHost = ::gethostbyaddr((LPSTR)&dwIP, 4, AF_INET);
char szHostName[256]={0};
strncpy(szHostName, pHost->h_name, 256);
//得到網(wǎng)絡(luò)數(shù)據(jù)
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 "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();
//設(shè)置圖標(biāo)
SetIcon(theApp.LoadIconA(IDI_MAIN), FALSE);
//創(chuàng)建狀態(tài)欄并設(shè)置其屬性
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程序設(shè)計(jì)", 1, 0);
m_bar.SetText("空閑", 0, 0);
//關(guān)聯(lián)列表控件
m_listInfo.SubclassDlgItem(IDC_LIST, this);
//初始化套接字和連接列表
m_socket = INVALID_SOCKET;
m_nClient = 0;
//取得本機(jī)IP,在狀態(tài)欄中顯示
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("本機(jī)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);
}
//創(chuàng)建套接字
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);
//進(jìn)入監(jiān)聽模式
::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) //開啟服務(wù)
{
CString strPort;
GetDlgItem(IDC_PORT)->GetWindowText(strPort);
int nPort = atoi(strPort);
if (nPort < 1 || nPort >65535)
{
MessageBox("port error");
return;
}
//創(chuàng)建套接字
if (!this->CreateAndListen(nPort))
{
MessageBox("create socket error");
return;
}
//設(shè)置控件狀態(tài)
GetDlgItem(IDC_START)->SetWindowTextA("停止服務(wù)");
m_bar.SetText("正在監(jiān)聽...", 0, 0);
GetDlgItem(IDC_PORT)->EnableWindow(FALSE);
}
else //關(guān)閉服務(wù)
{
CloseAllSocket();
GetDlgItem(IDC_START)->SetWindowTextA("開啟服務(wù)");
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;
//查看是否出錯(cuò)
if (WSAGETSELECTERROR(lParam))
{
RemoveClient(s);
::closesocket(s);
return 0;
}
//處理發(fā)生的事件
switch (WSAGETSELECTEVENT(lParam))
{
case FD_ACCEPT: //監(jiān)聽到有套接字中有連接進(jìn)入
{
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: //接收到對方發(fā)來的數(shù)據(jù)包
{
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
//獲得主機(jī)名稱
DWORD dwIP = ::inet_addr(strIP);
hostent* pHost = ::gethostbyaddr((LPSTR)&dwIP, 4, AF_INET);
char szHostName[256]={0};
strncpy(szHostName, pHost->h_name, 256);
//得到網(wǎng)絡(luò)數(shù)據(jù)
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頭文件如下:
復(fù)制代碼 代碼如下:
#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();
//開啟或停止服務(wù)
afx_msg void OnStart();
afx_msg void OnClear();
afx_msg long OnSocket(WPARAM wParam, LPARAM lParam);
BOOL CreateAndListen(int nPort);
//向客戶連接列表中加一個(gè)客戶
BOOL AddClient(SOCKET s);
//從客戶連接列表中移除一個(gè)客戶
void RemoveClient(SOCKET s);
//關(guān)閉所有連接
void CloseAllSocket();
protected:
SOCKET m_socket;
//兩個(gè)子窗口控件
CListBox m_listInfo;
CStatusBarCtrl m_bar;
//客戶連接列表
SOCKET m_arClient[MAX_SOCKET]; //套接字列表
int m_nClient; //上述數(shù)組的大小
DECLARE_MESSAGE_MAP()
};
#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();
//開啟或停止服務(wù)
afx_msg void OnStart();
afx_msg void OnClear();
afx_msg long OnSocket(WPARAM wParam, LPARAM lParam);
BOOL CreateAndListen(int nPort);
//向客戶連接列表中加一個(gè)客戶
BOOL AddClient(SOCKET s);
//從客戶連接列表中移除一個(gè)客戶
void RemoveClient(SOCKET s);
//關(guān)閉所有連接
void CloseAllSocket();
protected:
SOCKET m_socket;
//兩個(gè)子窗口控件
CListBox m_listInfo;
CStatusBarCtrl m_bar;
//客戶連接列表
SOCKET m_arClient[MAX_SOCKET]; //套接字列表
int m_nClient; //上述數(shù)組的大小
DECLARE_MESSAGE_MAP()
};
TCPClient.cpp源文件如下:
復(fù)制代碼 代碼如下:
#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();
//設(shè)置圖標(biāo)
SetIcon(theApp.LoadIconA(IDI_MAIN), FALSE);
//關(guān)聯(lián)控件
m_edit_text.SubclassDlgItem(IDC_EDIT_CONTENT, this);
//狀態(tài)欄
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程序設(shè)計(jì)", 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("已經(jīng)連接到服務(wù)器", 0, 0);
}
break;
case FD_CLOSE:
{
MessageBox("client:close");
OnConnect();
}
break;
}
return 0;
}
BOOL CMainDialog::Connect(LPCTSTR pszRemoteAddr, u_short nPort)
{
//創(chuàng)建套接字
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地址,就認(rèn)為是主機(jī)名稱
//從主機(jī)名得到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;
}
//填寫服務(wù)器信息
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) //連接服務(wù)器
{
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;
}
//設(shè)置用戶界面
GetDlgItem(IDC_CONNECT)->SetWindowText("取消");
m_bar.SetText("正在連接..", 0, 0);
}
else //斷開服務(wù)器
{
::closesocket(m_socket);
m_socket = INVALID_SOCKET;
//設(shè)置用戶界面
GetDlgItem(IDC_CONNECT)->SetWindowTextA("連接服務(wù)器");
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 "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();
//設(shè)置圖標(biāo)
SetIcon(theApp.LoadIconA(IDI_MAIN), FALSE);
//關(guān)聯(lián)控件
m_edit_text.SubclassDlgItem(IDC_EDIT_CONTENT, this);
//狀態(tài)欄
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程序設(shè)計(jì)", 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("已經(jīng)連接到服務(wù)器", 0, 0);
}
break;
case FD_CLOSE:
{
MessageBox("client:close");
OnConnect();
}
break;
}
return 0;
}
BOOL CMainDialog::Connect(LPCTSTR pszRemoteAddr, u_short nPort)
{
//創(chuàng)建套接字
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地址,就認(rèn)為是主機(jī)名稱
//從主機(jī)名得到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;
}
//填寫服務(wù)器信息
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) //連接服務(wù)器
{
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;
}
//設(shè)置用戶界面
GetDlgItem(IDC_CONNECT)->SetWindowText("取消");
m_bar.SetText("正在連接..", 0, 0);
}
else //斷開服務(wù)器
{
::closesocket(m_socket);
m_socket = INVALID_SOCKET;
//設(shè)置用戶界面
GetDlgItem(IDC_CONNECT)->SetWindowTextA("連接服務(wù)器");
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頭文件如下:
復(fù)制代碼 代碼如下:
#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();
////開啟或停止服務(wù)
//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);
////向客戶連接列表中加一個(gè)客戶
//BOOL AddClient(SOCKET s);
////從客戶連接列表中移除一個(gè)客戶
//void RemoveClient(SOCKET s);
////關(guān)閉所有連接
//void CloseAllSocket();
DECLARE_MESSAGE_MAP()
};
#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();
////開啟或停止服務(wù)
//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);
////向客戶連接列表中加一個(gè)客戶
//BOOL AddClient(SOCKET s);
////從客戶連接列表中移除一個(gè)客戶
//void RemoveClient(SOCKET s);
////關(guān)閉所有連接
//void CloseAllSocket();
DECLARE_MESSAGE_MAP()
};
希望本文所述對大家的C++程序設(shè)計(jì)有所幫助。
相關(guān)文章
C++?string如何獲取文件路徑文件名、文件路徑、文件后綴(兩種方式)
這篇文章主要介紹了C++?string如何獲取文件路徑文件名、文件路徑、文件后綴(兩種方式),具有很好的參考價(jià)值,希望對大家有所幫助。2023-06-06C語言二叉樹常見操作詳解【前序,中序,后序,層次遍歷及非遞歸查找,統(tǒng)計(jì)個(gè)數(shù),比較,求深度】
這篇文章主要介紹了C語言二叉樹常見操作,結(jié)合實(shí)例形式詳細(xì)分析了基于C語言的二叉樹前序,中序,后序,層次遍歷及非遞歸查找,統(tǒng)計(jì)個(gè)數(shù),比較,求深度等相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2018-04-04