Hp-Socket高性能网络库一--tcp组件push接收模型

一、开始

上一篇我们说到了Hp-Socket提供的3种接收模型,本篇通过代码示例一步一步教大家怎么使用hp-socket进行网络通信程序开发。

HP-Socket 提供 PUSH / PULL / PACK 等接收模型,应用程序可以灵活选择以手工方式、半自动方式或全自动方式处理封解包。

接收模型接收事件说明
PUSHOnReceive(pSender, dwConnID, pData, iLength)手工方式/原生方式
PULLOnReceive(pSender, dwConnID, iLength)半自动
PACKOnReceive(pSender, dwConnID, pData, iLength)全自动
  1. PUSH 模型组件触发监听器对象的 OnReceive(pSender, dwConnID, pData, iLength)事件时,应用程序需要立即处理接收到的数据,如:粘包处理、协议解析等。组件不会对应用层的数据处理工作提供任何协助。
  2. PULL 模型组件触发监听器对象的 OnReceive(pSender, dwConnID, iTotalLength) 事件时,应用程序根据应用层协议检测接收到的数据长度(iTotalLength)是否满足处理条件,选择性地进行处理。 当 iTotalLength 小于当前期望的长度时可以忽略本次事 件 ;当iTotalLength 大 于 或 等 于 当 前 期 望 的 长 度 时 , 循 环 调 用 组 件 的Fetch(dwConnID, pData, iDataLength) 方法把需要的数据拉取出来,直到剩余的数据长度小于当前期望的长度。PULL 模型适用于完全清楚应用层协议,并且应用层协议可以根据当前数据包得知下一个数据包长度的场景。典型的场景如 Head + Body, Head 长度固定,第一个数据包为 Head,通过 Head 得知 Body 的长度,接收完 Body 之后下一个数据包一定为 Head。
  3. PACK 模型组件触发监听器对象的 OnReceive(pSender, dwConnID, pData, iLength)事件时,会保证 pData 是一个完整的数据包。 PACK 模型组件会对应用程序发送的每个数据包自动加上 4 字节(32 位) 的包头, 组件接收到数据时根据包头信息自动分包, 每个完整数据包通过 OnReceive 事件发送给应用程序。

二、push模型练习

纯C语言编写,调用HPSocket4C动态库的形式,利用vs2019开发环境,一步步教你使用hp-socket框架进行socket通信开发,对新手非常友好。

2.1准备工作

2.1.1编译得到hp-socket的dll和lib

在HP-Socket\Windows\Project目录下,打开HPSocket-2019.sln,直接编译,会在Bin目录下生成HPSocket4C_D.dll,HPSocket4C_D.lib两个文件。
编译好后会得到两个版本:c++版本(HPSocket)
c版本(HPSocket4C)
dll,lib文件

2.2开发步骤

2.2.1 新建项目工程

打开vs2019新建c++空项目TcpServer_push,我们选取hp-socket最原生的push接收模型,对push、pull、pack不清楚的可以查看上一篇《Hp-Socket高性能网络库介绍零--整体结构》,里面有详细描述三者的区别。
TcpServer_push c++空项目

2.2.2添加hp-socket头文件和lib,dll文件到项目中

1)添加头文件

复制ldcsaa-HP-Socket-master\HP-Socket\Windows\Include\HPSocket目录下两个h文件到项目目录下
添加hp头文件到项目

2)添加lib文件和dll文件

a.复制ldcsaa-HP-Socket-master\HP-Socket\Windows\Bin\HPSocket4C\x86目录下dll、lib文件到项目目录下
添加hp-socket lib文件到项目
b.附加依赖项
在这里插入图片描述

2.2.3编写main.cpp

server端编码原则我们是按照hp-socket development guide来的,可以看到跟原生的socket编程差不多。

监听器接口回调事件描述
ISocketListenerTOnHandShake()握手完成
ISocketListenerTOnSend()数据已发送
ISocketListenerTOnReceive()数据到达
ISocketListenerTOnClose连接关闭
IComplexSocketListenerTOnShutdown关闭通信组件
IServerListenerTOnPrepareListen()准备监听
IServerListenerTOnAccept()接受连接请求

具体步骤:
1.创建监听器对象
2.创建 Socket 对象
3.设置 Socket 监听器回调函数

一共只有7个回调函数,自己处理好即可。代码如下,不超过80行,即实现了简单的tcp server框架搭建。

#include "HpInclude/HPSocket4C.h"
#include <stdio.h>

En_HP_HandleResult __stdcall OnPrepareListen(HP_Server pSender, SOCKET soListen)
{
	TCHAR szAddress[50];
	int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
	USHORT usPort;

	::HP_Server_GetListenAddress(pSender, szAddress, &iAddressLen, &usPort);
	return HR_OK;
}

En_HP_HandleResult __stdcall OnAccept(HP_Server pSender, HP_CONNID dwConnID, SOCKET soClient)
{
	BOOL bPass = TRUE;
	TCHAR szAddress[50];
	int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
	USHORT usPort;

	::HP_Server_GetRemoteAddress(pSender, dwConnID, szAddress, &iAddressLen, &usPort);

	printf("%s:%d connected...\n", szAddress, usPort);
	return bPass ? HR_OK : HR_ERROR;
}

En_HP_HandleResult __stdcall OnSend(HP_Server pSender, HP_CONNID dwConnID, const BYTE* pData, int iLength)
{
	return HR_OK;
}

En_HP_HandleResult __stdcall OnReceive(HP_Server pSender, HP_CONNID dwConnID, const BYTE* pData, int iLength)
{
	printf("receive data [connID=%d]:%s\n", dwConnID, pData);
	return HR_OK;
}

En_HP_HandleResult __stdcall OnClose(HP_Server pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode)
{
	printf("[connID=%d] closed\n", dwConnID);
	return HR_OK;
}

En_HP_HandleResult __stdcall OnShutdown(HP_Server pSender)
{
	return HR_OK;
}

int main()
{
	HP_TcpServer m_pServer;
	HP_TcpServerListener m_pListener;

	// 创建监听器对象
	m_pListener = ::Create_HP_TcpServerListener();
	// 创建 Socket 对象
	m_pServer = ::Create_HP_TcpServer(m_pListener);

	// 设置 Socket 监听器回调函数
	::HP_Set_FN_Server_OnPrepareListen(m_pListener, OnPrepareListen);
	::HP_Set_FN_Server_OnAccept(m_pListener, OnAccept);
	::HP_Set_FN_Server_OnSend(m_pListener, OnSend);
	::HP_Set_FN_Server_OnReceive(m_pListener, OnReceive);
	::HP_Set_FN_Server_OnClose(m_pListener, OnClose);
	::HP_Set_FN_Server_OnShutdown(m_pListener, OnShutdown);

	if (::HP_Server_Start(m_pServer, "127.0.0.1", 6000))
	{
		printf("start tcp server successfully\n");
	}
	else
	{
		printf("start tcp server failed\n");
		return 0;
	}

	getchar();
}

至此F7应该能编译成功,如果编译不成功,查看下是否是“使用多字节字符集

运行如下:
在这里插入图片描述

三、最后

通过本篇的讨论,我们了解了一般tcp网络通信程序中需要考虑的几点问题,学习了hp-socket的3种接收模型,并完成了push接收模型的tcp server框架的纯c语言版本,希望对socket或hp-socket框架初学者有一定帮助。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苏克贝塔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值