E009

调用orsci-art中的P2P,实现P2P多线程网络编程演示。

 

#pragma once

#include "JWP2P.h"

using namespace art;

namespace TEST_P2P
{


class TMyP2P : public TP2P
{
public: //多线程模式下的时间触发
virtual void OnAccept(const string & ARemoteIP, const int & ARemotePort, bool & retAcceptAllowFlag) override
{
cout << "MyP2P::OnAccept()" << ARemoteIP << " : " << ARemotePort << endl;
}
virtual void OnConnect(_TP2PSocket & ASocket, const string & ARemoteIP, const int & ARemotePort, void * & userDefinedPointer) override
{
cout << "MyP2P::OnConnect()" << ARemoteIP << " : " << ARemotePort << endl;
}
virtual void OnDisconnect(_TP2PSocket & ASocket, const string & ARemoteIP, const int & ARemotePort, void * & userDefinedPointer) override
{
cout << "MyP2P::OnDisconnect()" << ARemoteIP << " : " << ARemotePort << endl;
}
virtual void OnSendData(_TP2PSocket & ASocket, const string & ARemoteIP, const int & ARemotePort, const char * ADataBuffer, const int ADataLen, const void * userDefinedPointer) override
{
cout << "MyP2P::OnSendData()" << ARemoteIP << " : " << ARemotePort << endl;
}
virtual void OnRecvData(_TP2PSocket & ASocket, const string & ARemoteIP, const int & ARemotePort, const char * ADataBuffer, const int ADataLen, const void * userDefinedPointer) override
{
cout << "MyP2P::OnRecvData()" << ARemoteIP << " : " << ARemotePort << " 数据长度:" << ADataLen << endl;
int mValue;
if (ADataLen == sizeof(int))
{
TMemoryStreamLimitLengthBufferTool mm((char *)ADataBuffer, ADataLen, orsci::esot_ReadOnly);
mm.resize(ADataLen);
mm.reset();

mValue = mm.readint32();
cout << "假设按照整数解析,数据值:" << mValue << endl;
}
}
virtual void OnException(int AExceptionCode, const string & AExceptionMsg, bool & retIgnoreException) override
{
cout << "MyP2P::OnException()" << AExceptionCode << " -- " << AExceptionMsg << endl;
}
};


inline void DemoTest_P2P()
{
cout << "===========================================" << endl;
cout << "// P2P 2.0 Demo" << endl;
cout << "http://www.orsci.cn; http://www.jiang.cn" << endl;
cout << "Hint:当输入IP地址时,如果输入1,则按照127.0.0.1执行" << endl;
cout << "===========================================" << endl;
TNetTools::Demo_DispLocalNetWorkInfo();

TMyP2P pp;
cout << "操作说明:" << endl;
cout << "0--进行统计输出, 100--之后退出" << endl;
cout << "9--显示当前客户列表!" << endl;
//cout << "
cout << "5--启动服务; 6--关闭服务!" << endl;
cout << "7--连接指定用户; 8--断开指定用户" << endl;
cout << "1--发送数据" << endl;

//if (false)
//{
// TP2P::_TDuanMap aa;
// aa.RegistClientMap("127.0.0.1", 12, "127.0.0.1", 1122, TP2P::ecet_InClientSocket);
// aa.RegistClientMap("127.0.0.1", 34, "127.0.0.1", 3344, TP2P::ecet_InClientSocket);
// aa.RegistClientMap("127.0.0.1", 56, "127.0.0.1", 5566, TP2P::ecet_InClientSocket);
// cout << aa.export_MapInfo() << endl;
// cout << "==============================" << endl;
// cout << aa.export_RecvMapInfo() << endl;
// cout << "------------------------------" << endl;
// vector<_RIPPortAddress> mList;
// aa.UnRegistClientMap("127.0.0.1", 34, mList);
// cout << aa.export_MapInfo() << endl;
// cout << "==============================" << endl;
// cout << aa.export_RecvMapInfo() << endl;
// cout << "------------------------------" << endl;
// return;
//}
string mIP;
cout << "请输入本地IP(例如127.0.0.1):";
while (mIP == "") cin >> mIP;
if (mIP.size() < 5) mIP = "127.0.0.1";
//pp.BoundLocal("127.0.0.1", 0);
pp.BoundLocal(mIP, 0);
pp.Open();
cout << "本地端口:" << pp.LocalPort() << endl;
while (true)
{
cout << "输入命令数值(大于100退出):";
int mCommand;
cin >> mCommand;
if (mCommand >= 100) break;
if (mCommand == 1)
{
string mPeerIP;
cout << "请输入目标用户IP地址(如127.0.0.1):";
while (mPeerIP == "") cin >> mPeerIP;
unsigned short int mPeerPort = 0;
cout << "[发送数据]请输入目标用户的端口(注:0中止操作):";
cin >> mPeerPort;
if (mPeerPort > 0)
{
int mValue = rand();
cout << "请输入一个将要发送的整数:";
cin >> mValue;
int mErrorCode = 0;
int mFlag = pp.SendBuffer("127.0.0.1", mPeerPort, (char *)&mValue, sizeof(mValue), mErrorCode);
cout << "发送标识:" << mFlag << " 数据值:" << mValue << endl;
}
}
if (mCommand == 5)
{
if (pp.is_active())
cout << "服务器已经启动" << endl;
else
pp.Open();
cout << "本地端口:" << pp.LocalPort() << endl;
}
if (mCommand == 6)
{
if (pp.is_active() == false)
cout << "服务器已经关闭!" << endl;
else
pp.Close();
}
if (mCommand == 7)
{
string mPeerIP;
cout << "请输入远程IP地址(如127.0.0.1):";
while (mPeerIP == "") cin >> mPeerIP;
if (mPeerIP.size() < 5) mPeerIP = "127.0.0.1";
unsigned short int mPeerPort = 0;
cout << "请输入要连接用户的端口(注:0中止操作):";
cin >> mPeerPort;
if (mPeerPort > 0)
{
//pp.Connect("127.0.0.1", mPeerPort);
pp.Connect(mPeerIP, mPeerPort);
}
}
if (mCommand == 8)
{
string mPeerIP;
cout << "请输入要断开的用户IP地址(如127.0.0.1):";
while (mPeerIP == "") cin >> mPeerIP;
if (mPeerIP.size() < 5) mPeerIP = "127.0.0.1";
unsigned short int mPeerPort = 0;
cout << "请输入要断开的用户的端口(注:0中止操作):";
cin >> mPeerPort;
if (mPeerPort > 0)
{
//pp.Disconnect("127.0.0.1", mPeerPort);
pp.Disconnect(mPeerIP, mPeerPort);
}
}
if (mCommand == 9)
{
cout << "[Info]本地地址:" << pp.LocalIP() << " : " << pp.LocalPort() << endl;
//cout << "=======客户表中的所有连接映射信息===========" << endl;
//cout << pp.export_ClientMapInfo(2) << endl;
//cout << endl;
//cout << "=======客户表中的Raw信息===========" << endl;
//pp.temp_getClientTable().DispClientInfoTable(0);
//cout << "=======服务器表中的Raw信息===========" << endl;
//pp.tcpservtemp_getClientTable().DispClientInfoTable(0);
pp.DispInDos_TableInfo();
}
}

cout << "程序结束!" << endl;
//char xxpp;
//cin >> xxpp;
}

};


inline void E009_Demo()
{
TEST_P2P::DemoTest_P2P();
}

输出

(一)Peer端One运行图

.用户1运行图

(二)Peer端Two运行图

用户2运行图

(三)Peer端Three运行图

用户3运行图

(四)说明:

(1)P2P按照对等模式实现网络编程。任意一端都可以连接其它端,各端是对等的,没有服务中心的概念。只是应用程序设计时,通常故意将某一端设置为具有管理能力的一端,而其它各端之间仍然可以自由连接。

(2)前面程序展示用户2和用户3连接用户1,此外,还可以实现用户2和用户3连接,类似,还可以增加更多的用户端。不同于TCP中存在一个Server,P2P中的这些端之间可以自由连接。

(3)该P2P的设计和工作原理,请参看书籍:姜维. 《分布式网络系统与Multi-Agent系统编程框架》

(3)在orsci-art包中,使用TP2P类作为基础类,派生出子类后创建P2P编程中的一个用户端。

(4)orsci包支持P2P网络编程,提供TP2P基础类,可下载配套软件orsci进行应用。

书籍 姜维. 《分布式网络系统与Multi-Agent系统编程框架》
软件 orsci-art开发包(C++语言)。