NetProcess是一个在Windows系统中实现TCP连接和数据传输功能的代码模块。
轻便易用,只需4个文件即可在你的代码中整合网络传输功能。
提供性能和可扩展性的保障,模块使用线程池机制实现,同时处理多至数千个连接并收发数据,可同时建立多个网络服务和客户端连接。
适合VC++32位及64位编译环境,测试程序使用Visual Studio 2019及MFC实现。
以下简要说明代码的使用方式,具体实现见测试代码。
在你的工程中包含以下4个代码文件即可整合网络传输功能:
NetProcess.h -- 网络传输功能代码头文件;
NetProcess.cpp -- 网络传输功能代码实现文件;
PQueue.h -- 一个队列模板类;
PSyncQueue.h -- 一个线程安全的队列模板类。
其他文件为测试程序使用。
指示一个线程中的socket连接,并定义数据连接和发送的功能。其中id指定本地标识,用于使用者标明一个连接。
定义连接状态的类,包括IP地址和收发数据量等信息。
包括连接、状态、数据及数据长度的类,使用智能指针实现,可自动销毁资源,便于在线程之间传送状态和数据。
代码中定义以下几种数据传输模式,跟据不同模式收发数据包。模式由listen和connect函数的mode参数指定,要求服务端和客户端一致。
#define _NET_MODE_MESSAGE 1 //字节消息传输,要求指定结束符
#define _NET_MODE_WIDE_MESSAGE 2 //宽字节消息传输,要求指定结束符
#define _NET_MODE_PACKET 3 //整包传输,包头指定数据长度
#define _NET_MODE_FIXED 4 //接收定长数据,不改变发送数据
#define _NET_MODE_CELL 5 //传输(发送和接收)定长数据,发送数据按定长分组
#define _NET_MODE_DATA 6 //传输无格式数据
_NET_MODE_MESSAGE:以结束符分隔的数据传输模式,可用于文本消息的传输。listen和connect函数的letter参数指定分隔符。发送数据时在包的结尾自动添加分隔符,接收数据时检查并去掉分隔符,保证用户收到为完整的数据包(不包括分隔符)。
_NET_MODE_WIDE_MESSAGE:用于宽字节(wchar_t)文本消息的传输,其它与_NET_MODE_MESSAGE模式相同。
_NET_MODE_PACKET:包数据传输模式,可用于二进制数据的传输。发送数据时在用户数据前添加数据长度信息,接收数据时首先接收长度信息,再接收此长度的数据完成后提供给用户,保证用户收到为完整的数据包(不包括附加的数据长度)。
_NET_MODE_FIXED:定长数据包传输模式,发送原始数据,不添加任何信息。listen和connect函数的letter参数指定数据长度,接收到letter长度的数据后提供给用户,保证用户收到该长度的数据包。
_NET_MODE_CELL:信元传输模式,程序将数据分割为指定长度的信元并发送。listen和connect函数的letter参数指定信元数据长度,接收到letter长度的数据后提供给用户。此模式可能用在快速数据转发的场景中;此模式不会将数据组合为完整的数据包,因此需要使用者自定义信元数据的处理方式(例如:使用第一个信元指定接收者、数据类型、长度、信元数等信息)。
_NET_MODE_DATA:无格式数据传输模式,发送和接收原始数据,不添加任何信息。收到的数据可能因缓冲的原因而被分割在不同的包中。
初始化网络环境,启动线程。调用startNetProcess函数,指定回调函数。
//启动网络连接线程,参数为指定的数据接收回调函数
bool startNetProcess(PNotifyFunction fun);
程序使用回调机制实现与使用者的通讯,fun 为接收数据和状态消息的回调函数指针;使用者需定义这个函数以接收网络状态和数据通知,回调函数类型的定义如下:
typedef void (*PNotifyFunction)(PNetItem item);//接收网络数据和连接状态的回调函数类型
调用exitNetProcess函数,退出网络线程,断开所有当前的连接及销毁关联的资源。
//退出网络线程,断开所有当前的连接
void exitNetProcess();
建立一个监听连接(同时指定连接模式及参数),调用静态函数listen,代码形式如下:
PNetLink::listen("0.0.0.0", 9999);
或者
PNetLink::listen("0.0.0.0", 9999, 0, _NET_MODE_MESSAGE, 127);
listen函数参数说明:
ip,port:ip地址和端口;
_id:本地标识,由使用者指定此连接的编号;
_limit:数据包的最大长度。
//网络服务端,建立网络监听 _id:监听socket的本地标识,limit数据包的最大长度
static void listen(const char* ip, int port, int _id = 0, int _mode = _NET_MODE_PACKET, int _letter = 0, int _limit = _NET_PACKET_LIMIT);
static void listen(const wchar_t* ip, int port, int _id = 0, int _mode = _NET_MODE_PACKET, int _letter = 0, int _limit = _NET_PACKET_LIMIT);
接受连接:
程序通过回调函数通知用户,item的code()值为_NET_CODE_ACCEPT时,即为接受到新的连接。
以下代码作为说明,其中item为传入的参数,link为用户定义的连接。
PNetItem item;//收到的连接参数
if (item.code() == _NET_CODE_ACCEPT)
{
PNetLink link = item;//将收到的连接赋值给本地连接
}
接受的连接会继承监听连接的属性(包括模式、letter及数据包最大长度)。
建立一个连接,调用静态函数connect,代码形式如下:
PNetLink::connect("127.0.0.1", 9999, 1);
或者
PNetLink::connect("127.0.0.1", 9999, 1, _NET_MODE_MESSAGE, 127);
connect函数参数说明:
ip,port:ip地址和端口;
_id:本地标识,由使用者指定此连接的编号;
_limit:数据包的最大长度。
//客户端建立网络连接,指定ip地址和端口,_id本地标识,_limit数据包的最大长度
static void connect(const char* ip, int port, int _id = 0, int _mode = _NET_MODE_PACKET, int _letter = 0, int _limit = _NET_PACKET_LIMIT);
static void connect(const wchar_t* ip, int port, int _id = 0, int _mode = _NET_MODE_PACKET, int _letter = 0, int _limit = _NET_PACKET_LIMIT);
连接成功通知:
调用connect函数之后并不会立即得到网络连接,程序会调用回调函数通知用户,当item的code()值为_NET_CODE_CONNECT时,表示连接成功。
item为新连接,id()属性确定此连接的身份,因此必要时使用者需在调用connect函数时指定id。
code()值为_NET_FAIL_CONNECT时,表示网络连接失败。
如何接受成功的连接,以下代码作为说明,其中item为传入的参数,link为用户定义的连接。
PNetItem item;//收到的连接参数
if (item.code() == _NET_CODE_CONNECT)
{
PNetLink link = item;//将收到的连接赋值给本地连接
}
调用PNetLink类的send函数发送数据。
//以下发送函数发送数据包,数据传输格式由连接的mode确定,函数将多组数据合并发送
//CELL模式将每组数据按cell发出,不会跨越组
void send(const char* p);
void send(const wchar_t* p);
void send(const char* p, int len);
void send(const char* p1, int len1, const char* p2, int len2);
void send(const char* p1, int len1, const char* p2, int len2, const char* p3, int len3);
程序调用回调函数通知用户,当item的code()值为_NET_CODE_DATA时,表示接收到数据。
_NET_MODE_MESSAGE、_NET_MODE_WIDE_MESSAGE及_NET_MODE_PACKET传输模式,此时收到的为完整数据包(不包括分隔符、数据长度等附加信息);
_NET_MODE_FIXED、_NET_MODE_CELL传输模式,此时收到的为定长(长度为letter)数据包。
对于声明形式如下的回调函数
void recvFunction(PNetItem item);
参数item为收到数据的连接,item的data()和length()属性为数据指针和长度。
程序在发送和接收数据失败时会断开此连接,并向用户通知错误信息。
程序调用回调函数向用户通知网络状态。
对于声明形式如下的回调函数
void recvFunction(PNetItem item);
参数item为状态的连接,item的code()为网络状态码;当item的code()为_NET_CODE_STAT时,state()包含连接状态的信息(ip地址、端口、收发数据量等)。
以下为网络状态编码定义:
#define _NET_CODE_DATA 0
#define _NET_CODE_LISTEN 1
#define _NET_CODE_CONNECT 2
#define _NET_CODE_ACCEPT 3
#define _NET_CODE_DISCONNECT 4
#define _NET_CODE_STAT 5
#define _NET_CODE_EXIT -1
#define _NET_FAIL_THREAD -2
#define _NET_FAIL_LISTEN -3
#define _NET_FAIL_CONNECT -4
#define _NET_FAIL_ACCEPT -5
#define _NET_REJECT_CONNECT -6
#define _NET_LOST_CONNECT -7
#define _NET_FAIL_SEND -8
#define _NET_FAIL_RECV -9
#define _NET_ERROR_EVENT -10
code > 0 时表示一个状态正常的网络通知消息。
code == 0 时表示收到数据的通知消息。
code < 0 时表示网络连接发生错误,这时此连接已经断开。
调用getNetCodeDescribe函数,可获得状态代码的文本描述。
//获得消息编码的文本说明
const char * getNetCodeDescribe(int code);
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。