基于异步通知的网络socket通信案例一

服务端

stdafx.h

#ifndef MFCTEST_HEAD
#define MFCTEST_HEAD
#pragma once
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <afxwin.h>
#include <afxframewndex.h>
#include <Winsock2.h>
#include <assert.h>
#pragma comment (lib,"ws2_32.lib")



class CMyApp:public CWinApp
{
public:
	//构造函数
	CMyApp();
	//析构函数
	virtual ~CMyApp();

	//重载函数
public:
	//初始函数
	virtual BOOL InitInstance();
};



class CMyWindow : public CFrameWndEx
{
public:
	CButton												m_button;								 //按钮
	SOCKET												m_socket;								//连接句柄
	SOCKET												m_ClientSocket;					//客户端句柄	

public:
	//构造函数
	CMyWindow();
	//析构函数
	virtual ~CMyWindow();

	//虚函数
public:
	//命令响应消息
	virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);


	// 消息函数
protected:
	// 网络读取
	LRESULT OnSocketNotifyRead(WPARAM wParam, LPARAM lParam);
	// 网络关闭
	LRESULT OnSocketNotifyClose(WPARAM wParam, LPARAM lParam);
	// 网络连接
	LRESULT OnSocketNotifyAccept(WPARAM wParam, LPARAM lParam);

	//消息映射
public:
	//创建消息
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	//网络消息
	afx_msg LRESULT OnSocket(WPARAM  wParam, LPARAM lParam);
	DECLARE_MESSAGE_MAP()
};



#endif

afxmain.cpp

#include "stdafx.h"

CMyApp myapp;

#define						WM_SOCKET							WM_USER+1					//网络消息
#define						IDC_START							1012								 //按钮定义

//构造函数
CMyApp::CMyApp()
{

}

//析构函数
CMyApp::~CMyApp()
{

}

//初始函数
BOOL CMyApp::InitInstance()
{
	m_pMainWnd = new CMyWindow();
	m_pMainWnd->ShowWindow(SW_SHOW);
	m_pMainWnd->UpdateWindow();
	return TRUE;
}



BEGIN_MESSAGE_MAP(CMyWindow, CFrameWndEx)
	ON_WM_CREATE()
	ON_MESSAGE(WM_SOCKET, OnSocket)
END_MESSAGE_MAP()

//构造函数
CMyWindow::CMyWindow()
{
	//设置变量
	m_ClientSocket = INVALID_SOCKET;
	m_socket= INVALID_SOCKET;

	//创建窗口
	Create(NULL, TEXT("My Window"));
}
//析构函数
CMyWindow::~CMyWindow()
{
	WSACleanup();
}

//命令响应消息
BOOL CMyWindow::OnCommand( WPARAM wParam, LPARAM lParam )
{
	int wmId=LOWORD(wParam);
	switch (wmId)
	{
	case IDC_START:
		{
			MessageBox(TEXT("测试一下哈"),TEXT("提示"),MB_OK);
			return true;
		}
		break;
	default:
		return true;
	}

	return __super::OnCommand(wParam,lParam);

}

//创建事件
int CMyWindow::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
	__super::OnCreate(lpCreateStruct);

	//居中窗口
	SetActiveWindow();
	SetForegroundWindow();
	CenterWindow(GetParent());

	//创建按钮
	RECT rect={0,0,50,30};
	m_button.Create(TEXT("按钮"),WS_CHILD|WS_VISIBLE,rect,this,IDC_START);


	//启动使用ws2.dll的
	WORD wVersionRequested = MAKEWORD(2, 2);
	WSADATA lpWSAData = { 0 };
	WSAStartup(wVersionRequested, &lpWSAData);

	//创建socket
	m_socket = socket(AF_INET, SOCK_STREAM, 0);

	//绑定端口
	SOCKADDR_IN addr = { 0 };
	addr.sin_addr.S_un.S_addr =INADDR_ANY;
	addr.sin_family = AF_INET;
	addr.sin_port = 8012;
	if(bind(m_socket, (SOCKADDR*)&addr, sizeof(addr))== SOCKET_ERROR)
		throw TEXT("绑定端口失败");

	//绑定窗口
	int iErrorCode = WSAAsyncSelect(m_socket, this->m_hWnd, WM_SOCKET, FD_READ  | FD_ACCEPT |FD_CLOSE);
	if (iErrorCode == SOCKET_ERROR) throw TEXT("绑定内部窗口错误");

	//监听
	listen(m_socket, 5);

	return true;
}

//网络消息
LRESULT CMyWindow::OnSocket(WPARAM  wParam, LPARAM lParam)
{

	switch (WSAGETSELECTEVENT(lParam))
	{
	case FD_ACCEPT:		//网络连接
	{
		return OnSocketNotifyAccept(wParam, lParam);
	}
	case FD_READ: // 数据读取
	{
		return OnSocketNotifyRead(wParam, lParam);
	}
	case FD_CLOSE: // 网络关闭
	{
		return OnSocketNotifyClose(wParam, lParam);
	}
	}

	return 0;
}

// 网络读取
LRESULT CMyWindow::OnSocketNotifyRead(WPARAM wParam, LPARAM lParam)
{
	try
	{
		ASSERT(m_ClientSocket != INVALID_SOCKET);
		if (m_ClientSocket == INVALID_SOCKET)return false;

		// 读取数据
		char  szText[1024] = { 0 };
		int iRetCode = recv(m_ClientSocket, szText, 1024, 0);
		if (iRetCode == SOCKET_ERROR) throw TEXT("网络连接关闭,读取数据失败");

		char szSendText[64] = { "这是服务端发送的消息" };
		send(m_ClientSocket, szSendText, 64, 0);
	}
	catch (...)
	{
		closesocket(m_ClientSocket);
	}
	return true;
}



// 网络关闭
LRESULT CMyWindow::OnSocketNotifyClose(WPARAM wParam, LPARAM lParam)
{
	closesocket(m_ClientSocket);
	return true;
}

// 网络连接
LRESULT CMyWindow::OnSocketNotifyAccept(WPARAM wParam, LPARAM lParam)
{
	SOCKADDR_IN clientaddr = { 0 };
	INT nBufferSize = sizeof(clientaddr);
	m_ClientSocket = accept(m_socket, (SOCKADDR*)&clientaddr, &nBufferSize);
	//退出判断
	if (m_ClientSocket == INVALID_SOCKET) return false;
	return true;
}



客户端

WHSocketHead.h

#pragma once
#pragma pack(1)
#include <Winsock2.h>
#include <assert.h>
#pragma comment (lib,"ws2_32.lib")

#pragma pack(1)

//网络命令
struct TCP_Command
{
	WORD							wMainCmdID;							//主命令码
	WORD							wSubCmdID;							//子命令码
};
#pragma pack()



//网络状态
#define					SOCKET_STATUS_IDLE			0									//空闲状态
#define					SOCKET_STATUS_WAIT			1									//等待状态
#define					SOCKET_STATUS_CONNECT	2									//连接状态

//关闭原因
#define				SHUT_REASON_INSIDE				0									//内部原因
#define				SHUT_REASON_NORMAL			1									//正常关闭
#define				SHUT_REASON_REMOTE			2									//远程关闭
#define				SHUT_REASON_TIME_OUT		3									//网络超时
#define				SHUT_REASON_EXCEPTION		4									//异常关闭

//网络接口
__interface ITCPSocketSink
{
	//网络事件
public:
	//连接事件
	virtual bool OnEventTCPSocketLink(WORD wSocketID, INT nErrorCode) = NULL;
	//关闭事件
	virtual bool OnEventTCPSocketShut(WORD wSocketID, BYTE cbShutReason) = NULL;
	//读取事件
	virtual bool OnEventTCPSocketRead(WORD wSocketID, TCP_Command Command, VOID * pData, WORD wDataSize) = NULL;
};

stdafx.h

#ifndef MFCTEST_HEAD
#define MFCTEST_HEAD
#pragma once
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <afxwin.h>
#include <afxframewndex.h>
#include "WHSocketHead.h"



//////////////////////////////////////////////////////////////////////////////////

class CMyApp:public CWinApp
{
public:
	//构造函数
	CMyApp();
	//析构函数
	virtual ~CMyApp();

	//重载函数
public:
	//初始函数
	virtual BOOL InitInstance();
};



class CMyWindow : public CFrameWndEx
{
public:
	CButton												m_button;								 //按钮
	SOCKET												m_socket;								//连接句柄
	BYTE													m_cbSocketStatus;				//网络状态
	WORD												m_wSocketID;						//网络标识


public:
	//构造函数
	CMyWindow();
	//析构函数
	virtual ~CMyWindow();

	//虚函数
public:
	//命令响应消息
	virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);

	//辅助函数
protected:
	// 关闭连接
	void CloseSocket(BYTE cbShutReason);

	// 消息函数
protected:
	// 网络读取
	LRESULT OnSocketNotifyRead(WPARAM wParam, LPARAM lParam);
	// 网络发送
	LRESULT OnSocketNotifyWrite(WPARAM wParam, LPARAM lParam);
	// 网络关闭
	LRESULT OnSocketNotifyClose(WPARAM wParam, LPARAM lParam);
	// 网络连接
	LRESULT OnSocketNotifyConnect(WPARAM wParam, LPARAM lParam);

	//消息映射
public:
	//创建消息
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	//网络消息
	afx_msg LRESULT OnSocket(WPARAM  wParam, LPARAM lParam);
	DECLARE_MESSAGE_MAP()
};

<pre name="code" class="cpp">#include "stdafx.h"

CMyApp myapp;

#define						WM_SOCKET							WM_USER+1					//网络消息
#define						IDC_START							1012								 //按钮定义

//构造函数
CMyApp::CMyApp()
{

}

//析构函数
CMyApp::~CMyApp()
{

}

//初始函数
BOOL CMyApp::InitInstance()
{
	m_pMainWnd = new CMyWindow();
	m_pMainWnd->ShowWindow(SW_SHOW);
	m_pMainWnd->UpdateWindow();
	return TRUE;
}



BEGIN_MESSAGE_MAP(CMyWindow, CFrameWndEx)
	ON_WM_CREATE()
	ON_MESSAGE(WM_SOCKET, OnSocket)
END_MESSAGE_MAP()

//构造函数
CMyWindow::CMyWindow()
{

	//设置变量
	m_socket= INVALID_SOCKET;
	m_wSocketID = NULL;
	m_cbSocketStatus = SOCKET_STATUS_IDLE;

	//创建窗口
	Create(NULL, TEXT("My Window"));
}
//析构函数
CMyWindow::~CMyWindow()
{
	WSACleanup();
}

//命令响应消息
BOOL CMyWindow::OnCommand( WPARAM wParam, LPARAM lParam )
{
	int wmId=LOWORD(wParam);
	switch (wmId)
	{
	case IDC_START:
		{
			MessageBox(TEXT("测试一下哈"),TEXT("提示"),MB_OK);
			return true;
		}
		break;
	default:
		return true;
	}

	return __super::OnCommand(wParam,lParam);

}

//创建事件
int CMyWindow::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
	__super::OnCreate(lpCreateStruct);

	//居中窗口
	SetActiveWindow();
	SetForegroundWindow();
	CenterWindow(GetParent());

	//创建按钮
	RECT rect={0,0,50,30};
	m_button.Create(TEXT("按钮"),WS_CHILD|WS_VISIBLE,rect,this,IDC_START);

	//启动使用ws2.dll的
	WORD wVersionRequested = MAKEWORD(2, 2);
	WSADATA lpWSAData = { 0 };
	WSAStartup(wVersionRequested, &lpWSAData);

	//创建socket
	m_socket = socket(AF_INET, SOCK_STREAM, 0);
	m_wSocketID = (WORD)m_socket;
	int iErrorCode = WSAAsyncSelect(m_socket, this->m_hWnd, WM_SOCKET, FD_READ   | FD_CONNECT | FD_CLOSE);
	if (iErrorCode == SOCKET_ERROR) throw TEXT("绑定内部窗口错误");

	//连接服务器
	SOCKADDR_IN addr = { 0 };
	addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	addr.sin_family = AF_INET;
	addr.sin_port = 8012;
	iErrorCode = connect(m_socket, (SOCKADDR*)&addr, sizeof(addr));
	if (iErrorCode == SOCKET_ERROR)
	{
		iErrorCode = WSAGetLastError();
		TCHAR szBuffer[64] = { 0 };
		if (iErrorCode != WSAEWOULDBLOCK)
		{
			_sntprintf_s(szBuffer, sizeof(szBuffer), TEXT("连接发生错误,错误代码 %d"), iErrorCode);
			throw szBuffer;
		}
		else if (iErrorCode == WSAEWOULDBLOCK)
		{
			_sntprintf_s(szBuffer, sizeof(szBuffer), TEXT("从操作返回的时候没有数据正在排队等待从套接字读取非阻塞无法立即完成的插座 %d"), iErrorCode);
			OutputDebugString(szBuffer);
		}
	}
	// 设置变量
	m_cbSocketStatus = SOCKET_STATUS_WAIT;

	char szText[64] = { "这是客户端发送的消息" };
	send(m_socket, szText, 64, 0);
	return true;
}

//网络消息
LRESULT CMyWindow::OnSocket(WPARAM  wParam, LPARAM lParam)
{

	switch (WSAGETSELECTEVENT(lParam))
	{
		case FD_CONNECT: // 网络连接
		{
			return OnSocketNotifyConnect(wParam, lParam);
		}
		case FD_READ: // 数据读取
		{
			return OnSocketNotifyRead(wParam, lParam);
		}
		case FD_CLOSE: // 网络关闭
		{
			return OnSocketNotifyClose(wParam, lParam);
		}
	}

	return 0;
}
// 网络读取
LRESULT CMyWindow::OnSocketNotifyRead(WPARAM wParam, LPARAM lParam)
{
	try
	{
		// 读取数据
		char szRecvText[1024] = { 0 };
		int iRetCode = recv(m_socket, szRecvText, 1024, 0);
		if (iRetCode == SOCKET_ERROR) throw TEXT("网络连接关闭,读取数据失败");

		// 处理数据
		//bool bSuccess = m_pITCPSocketSink->OnEventTCPSocketRead(m_wSocketID, Command, pDataBuffer, wDataSize);
		//if (bSuccess == false) throw TEXT("网络数据包处理失败");
	}
	catch (...)
	{
		closesocket(m_socket);
	}
	return true;
}


// 网络关闭
LRESULT CMyWindow::OnSocketNotifyClose(WPARAM wParam, LPARAM lParam)
{
	// 关闭连接
	ASSERT(m_socket != INVALID_SOCKET);
	if (m_socket == INVALID_SOCKET)return true;

	m_cbSocketStatus = SOCKET_STATUS_IDLE;
	WSAAsyncSelect(m_socket, GetSafeHwnd(), WM_SOCKET, 0);
	closesocket(m_socket);
	m_socket = INVALID_SOCKET;
	m_cbSocketStatus = SOCKET_STATUS_IDLE;

	//通知事件
	//try { m_pITCPSocketSink->OnEventTCPSocketShut(m_wSocketID, SHUT_REASON_NORMAL); }
	//catch (...) {}
	return true;
}

// 网络连接
LRESULT CMyWindow::OnSocketNotifyConnect(WPARAM wParam, LPARAM lParam)
{
	// 判断状态
	int iErrorCode = WSAGETSELECTERROR(lParam);
	if (iErrorCode == 0) m_cbSocketStatus = SOCKET_STATUS_CONNECT;
	else CloseSocket(SHUT_REASON_TIME_OUT);

	// 发送通知
	//m_pITCPSocketSink->OnEventTCPSocketLink(m_wSocketID, iErrorCode);
	return true;
}

// 关闭连接
void CMyWindow::CloseSocket(BYTE cbShutReason)
{
	// 关闭连接
	ASSERT(m_socket != INVALID_SOCKET);
	if (m_socket == INVALID_SOCKET)return;

	m_cbSocketStatus = SOCKET_STATUS_IDLE;
	WSAAsyncSelect(m_socket, GetSafeHwnd(), WM_SOCKET, 0);
	closesocket(m_socket);
	m_socket = INVALID_SOCKET;
	m_cbSocketStatus = SOCKET_STATUS_IDLE;

	return;
}

#endif

 
 

你可能感兴趣的:(基于异步通知的网络socket通信案例一)