C++ 开发P2P及时消息发送程序(2)
来源:互联网 发布:蜗牛seo 编辑:程序博客网 时间:2024/05/16 07:13
2009-04-11
徐龙
公司上sap后,一直很忙碌,没什和时间继续写....
这次先把写好的 p2p 网络库贴上来,没有完全测试,还有很多细节要完善.
Protocol.h
-----------------------------------------------------------------
#pragma once
#if !defined(PROTOCOL_H)
#define PROTOCOL_H
#include <list>
#include <map>
#include <queue>
#include <string>
#include <sstream>
using namespace std;
#define SRV_PORT 9000 // server listen port
#define SEND_MAX_SIZE (1024*4) // max size of a packet
#define UWAIT_TIMEOUT 50 // define how many ms to wait and else is timeout
#define WAIT_TIMES 3 // if timeout resend 3 times , else tell application error.
typedef char BUFFER[SEND_MAX_SIZE];
const char ProtocolFlag[] = {'L','X',0x16,0x11,0x20,0x8};
const DWORD Version = 101;
string IntToStr(int in )
{
ostringstream os;
os << in;
return os.str();
}
void Sockaddr_inToStr(sockaddr_in *saddr,string& str)
{
ostringstream os;
os << saddr->sin_addr.S_un.S_addr << saddr->sin_port;
str=os.str();
}
typedef struct userinfor
{
WCHAR szUserID[255];
DWORD dwIP;
DWORD dwPort;
}USER_INFOR;
typedef std::list<USER_INFOR *> UserList;
//define socket type
typedef enum socket_type
{
stClient = 1, // only peer client.
stServer = 2, // only accept client to regsite and connect other client through the server.
stBoth = 3, // as client and as server.
}SOCKET_TYPE;
// define packet type
typedef enum packet_type
{
ptEMPTY=1,
ptKEEPLINE = 10,
//connected peers new link
//ptP2P_NEW_LNK_REQ=3,//request side send request msg to other peer . A:0 -- > B:0
//ptP2P_NEW_LNK_WAT=5,//be requested side new socket and send the packet ,wait requestSide to connect. B:1 --> A:0
//ptP2P_NEW_LNK_FIN=7,//request side new socket and send the packet ,success to new link A:1 --> B:1
//peer host socket connect to other peer
//cmd other peer connect to me
ptP2S_CONN_REQ=21,// a peer's mainsocket send the packet to server's mainsocket A:0 --> S:0
ptS2P_CONN_CMD=22,// server's mainsocket receive ptP2S_CONN_REQ pakket then send ptS2P_CONN_CMD packet to target peer's mainsocket S:0 --> B:0
//
//connect to other peer
ptP2P_CONN_REQ=23,//a peer receive ptS2P_CONN_CMD or Appliction Call ConnectToPeer then the peer create new socket and new socket send the packet to other peer's mainsocket.. B:1 --> A:0
ptP2P_CONN_FIN=24,//a peer revcive ptP2P_CONN_REQ then create a new socket and send to other peer's socket ask the "A",success to connect. A:1 --> B:1
ptP2S_MSG=30,
ptS2P_MSG=31
} PACKET_TYPE;
typedef struct packet_header
{
packet_header():ePacketType(ptEMPTY),dwPacketSize(0),dwVersion(Version)
{
memcpy(aProtocolflag,ProtocolFlag,sizeof(ProtocolFlag));
dwPacketSize = sizeof(packet_header);
}
CHAR aProtocolflag[sizeof(ProtocolFlag)];
DWORD dwVersion;
PACKET_TYPE ePacketType; //pakcet type
DWORD dwPacketSize; // packet size , head size plus data size . is packet total size .
DWORD dwFromIp; // From Ip address
DWORD dwFromPort; // From server port
DWORD dwSeqNumber; // sender create a id
DWORD dwAckNumber; // ask the sender's id
//.....body data....pay attention: dwPacketSize - sizeof(PACKET_HEADER) is data size,and dwPacketSize is the data offset address
}PACKET_HEADER;
typedef struct P2S_CONN_REQ_PKT:packet_header // a peer send to server
{
DWORD dwConnToPeerIP;
DWORD dwConnToPort;
}P2S_CONN_REQ_PKT;
typedef struct S2P_CONN_CMD_PKT:packet_header // server send to a peer
{
DWORD dwReqPeerIP;
DWORD dwReqPeerPort;
}S2P_CONN_CMD_PKT;
#define MaxDataSize SEND_MAX_SIZE-sizeof(PACKET_HEADER);
#endif
---------------------------------------------------------------------------------
Udbsocket.h
---------------------------------------------------------------------------------
#pragma once
#include "Protocol.h"
#include "wsainitializer.h"
#include "Thread.h"
#include <stdlib.h>
class TUdpSocket;
typedef void (*tOnSending)(TUdpSocket *pUdpSocket,sockaddr *pToAddr,char* szBuff,const int BuffLen);
typedef void (*tOnReceiving)(TUdpSocket *pUdpSocket,char* szBuff,const int BuffLen);
typedef void (*tOnDisconnected)(TUdpSocket *pUdpSocket);
class TUdpSocket
{
public:
TUdpSocket(void);
~TUdpSocket(void);
TUdpSocket& operator=(const TUdpSocket& ) { return *this; }
bool Create(void);
bool Bind(int port);
int SendTo(const int dwIP,const int dwPort,const char* szBuff,const int BuffLen);
int SendTo(const char* szIP,const int dwPort,const char* szBuff,const int BuffLen);
int Send(const char* szBuff,const int BuffLen);
void Listen(void);
void Connect(void);
//property
tOnSending OnSending;
tOnReceiving OnReceiving;
tOnDisconnected OnDisconnected;
int ServerIp;
int ServerPort;
bool Connected;
private:
SOCKET m_Socket;
TThread *m_thread;
bool m_binded;
DWORD m_lastSndTime;
DWORD m_lastKeepTime;
DWORD m_waitTimes;
static void ReceiveData(LPVOID Parent);
};
--------------------------------------
Peersocket.h
--------------------------------------
#pragma once
#include "UdpSocket.h"
////class TUdpSocketKey
////{
////public:
//// TUdpSocketKey();
//// TUdpSocketKey(DWORD ip,DWORD port):m_ip(ip),m_port(port){};
//// TUdpSocketKey(sockaddr_in &ad):m_ip(ad.sin_addr.s_addr),m_port(ad.sin_port){};
//// ~TUdpSocketKey(void);
////
//// bool operator == (const TUdpSocketKey& y ) { return (m_ip == y.m_ip && m_port == y.m_port);};
//// bool operator != (const TUdpSocketKey& y ) { return !(m_ip == y.m_ip && m_port == y.m_port); };
//// bool operator < (const TUdpSocketKey& y ) { return ((m_ip < y.m_ip) || ((m_ip == y.m_ip) && (m_port < y.m_port))); };
//// bool operator > (const TUdpSocketKey& y ) { return ((m_ip > y.m_ip) || ((m_ip == y.m_ip) && (m_port > y.m_port))); };
//// bool operator <= (const TUdpSocketKey& y ) { return ((m_ip < y.m_ip) || ((m_ip == y.m_ip) && (m_port <= y.m_port))); };
//// bool operator >= (const TUdpSocketKey& y ) { return ((m_ip > y.m_ip) || ((m_ip == y.m_ip) && (m_port >= y.m_port))); };
////
////
////
////private:
//// DWORD m_ip;
//// DWORD m_port;
////};
typedef std::map<string,TUdpSocket*> TUdpSocketMap;
class TPeerSocket :
public TUdpSocket
{
public:
TPeerSocket(void);
~TPeerSocket(void);
void ConnecdToPeer(DWORD dwIP,DWORD dwPort); // to do create new socket and new socket send ptP2P_CONN_REQ
void RequestPeerToMe(DWORD dwIP,DWORD dwPort); // to do main socket send ptP2S_CONN_REQ to server
//property
socket_type eSocketType;
private:
TUdpSocketMap m_UdpSocketMap;
static void Sending(TUdpSocket *pUdpSocket,sockaddr *pToAddr,char* szBuff,const int BuffLen);
static void Receiving(TUdpSocket *pUdpSocket,char* szBuff,const int BuffLen);
};
;
-------------------------------------------------------------------------------------------------------------
Udpsocket.cpp
----------------------------------------------------------------------------------------------------------------------------
#include "StdAfx.h"
#include "UDPSocket.h"
//#include <iostream>
void TUdpSocket::ReceiveData(LPVOID Parent)
{
TUdpSocket* pudp=((TUdpSocket*)Parent);
BUFFER buf;
struct sockaddr_in recAddr;
int sockaddrLen=sizeof(sockaddr_in);
ZeroMemory(&buf,sizeof(buf));
int recSize=recvfrom(pudp->m_Socket,buf,SEND_MAX_SIZE,0,(struct sockaddr *)&recAddr,&sockaddrLen);
if (recSize>0)
{
if (recSize > sizeof(PACKET_HEADER))
{
int ip=ntohl(recAddr.sin_addr.s_addr);
int port = ntohs(recAddr.sin_port);
PACKET_HEADER *pPacketHeader = (PACKET_HEADER*)&buf;
pPacketHeader->dwFromIp = ip;
pPacketHeader->dwFromPort = port;
if(pudp->ServerIp != 0) // as a client
{
if(pudp->ServerIp ==ip && pudp->ServerPort==port && pPacketHeader->ePacketType==ptKEEPLINE)
{
pudp->m_lastKeepTime=::GetTickCount(); // record last recevied the ptkeeline packet time
pudp->Connected = true;
pudp->m_waitTimes = 0;
}
DWORD dwCT = ::GetTickCount();
if ((dwCT - pudp->m_lastKeepTime) > UWAIT_TIMEOUT) //time out
{
pudp->m_waitTimes++;
pudp->m_lastKeepTime=::GetTickCount();
if (pudp->m_waitTimes>WAIT_TIMES) // out the max times
{
pudp->Connected=false;
pudp->m_thread->Stop();
if (pudp->OnDisconnected!=NULL)
{
pudp->OnDisconnected(pudp);
}
}
}
}
}
if ( pudp->OnReceiving != NULL)
{
pudp->OnReceiving(pudp,(char*)&buf,recSize);
}
if(pudp->ServerIp != 0 && (::GetTickCount()-pudp->m_lastSndTime ) / 2 > UWAIT_TIMEOUT ) // as a client // snd keep line pkt
{
PACKET_HEADER sndPkt ;
sndPkt.ePacketType=ptKEEPLINE;
pudp->Send((const char*)&sndPkt,sizeof(sndPkt));
pudp->m_lastSndTime = ::GetTickCount();
}
}
}
TUdpSocket::TUdpSocket(void):m_Socket(INVALID_SOCKET),m_thread(NULL),m_binded(false),ServerIp(0),ServerPort(0)
{
m_thread = new TThread(this);
m_thread->OnExecute = ReceiveData;
}
TUdpSocket::~TUdpSocket()
{
if (m_Socket!=INVALID_SOCKET)
{
closesocket(m_Socket);
}
if (m_thread != NULL)
{
delete(m_thread);
}
}
void TUdpSocket::Listen()
{
if(m_binded && OnReceiving != NULL)
{
m_lastKeepTime=::GetTickCount();
m_thread->Start();
}
}
void TUdpSocket::Connect()
{
if(OnReceiving != NULL)
{
m_lastKeepTime=::GetTickCount();
m_thread->Start();
}
}
//绑定端口
bool TUdpSocket::Bind(int Port)
{
m_binded = false;
m_thread->Stop();
if (m_Socket!=INVALID_SOCKET)
{
int ret=0;
SOCKADDR_IN addr;
ZeroMemory(&addr,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(Port);
ret = bind(m_Socket,(struct sockaddr *)&addr,sizeof(addr));
if(ret!=0)
{
closesocket(m_Socket);
m_binded = false;
}
else
{
m_binded = true;
}
}
return m_binded;
}
//创建UDP套接字,并设置可重绑定
bool TUdpSocket::Create()
{
bool flag = true;
int ret=0;
m_Socket = socket(AF_INET,SOCK_DGRAM,IPPROTO_IP);
if(m_Socket==INVALID_SOCKET)
{
return false;
}
//设置套接字可重绑定(新实例会替掉旧实例)
ret = setsockopt(m_Socket,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag));
if(ret!=0)
{
closesocket(m_Socket);
return false;
}
return true;
}
int TUdpSocket::SendTo(const int dwIP, const int dwPort, const char *szBuff, const int BuffLen)
{
int ret = 0;
if(m_binded)
{
BUFFER buf;
SOCKADDR_IN addr;
ZeroMemory(&buf,sizeof(buf));
ZeroMemory(&addr,sizeof(addr));
memcpy(&buf,szBuff,BuffLen);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htons(dwIP);
addr.sin_port = htons(dwPort);
if ( OnSending != NULL)
{
OnSending(this,(sockaddr *)&addr,(char*)&buf,BuffLen);
}
ret= sendto(m_Socket,(char*)&buf,BuffLen,0,(sockaddr *)&addr,sizeof(addr));
}
return ret;
}
int TUdpSocket::SendTo(const char *szIP, const int dwPort, const char *szBuff, const int BuffLen)
{
int ret=0;
if(m_binded)
{
BUFFER buf;
SOCKADDR_IN addr;
ZeroMemory(&buf,sizeof(buf));
ZeroMemory(&addr,sizeof(addr));
memcpy(&buf,szBuff,BuffLen);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(szIP);
addr.sin_port = htons(dwPort);
if ( OnSending != NULL)
{
OnSending(this,(sockaddr *)&addr,(char*)&buf,BuffLen);
}
ret= sendto(m_Socket,(char*)&buf,BuffLen,0,(sockaddr *)&addr,sizeof(addr));
}
return ret;
}
int TUdpSocket::Send(const char *szBuff, const int BuffLen)
{
if (ServerIp != 0 && ServerPort != 0 )
{
return SendTo(ServerIp, ServerPort, szBuff, BuffLen);
}
return 0;
}
------------------------------------------------
Peersocket.cpp
--------------------------------------------
#include "StdAfx.h"
#include "PeerSocket.h"
void TPeerSocket::ConnecdToPeer(DWORD dwIP,DWORD dwPort) // to do create new socket and new socket send ptP2P_CONN_REQ
{
BUFFER sndBuf;
string key = IntToStr(dwIP) + IntToStr(dwPort);
TUdpSocket* pUdsItem = new TUdpSocket();
this->m_UdpSocketMap.insert(make_pair(key,pUdsItem));
pUdsItem->ServerIp=dwIP;
pUdsItem->ServerPort=dwPort;
pUdsItem->Connect();
ZeroMemory(&sndBuf,sizeof(sndBuf));
((PACKET_HEADER*)&sndBuf)->ePacketType = ptP2P_CONN_REQ;
memcpy(((PACKET_HEADER*)&sndBuf)->aProtocolflag,ProtocolFlag,sizeof(ProtocolFlag));
((PACKET_HEADER*)&sndBuf)->dwPacketSize = sizeof(PACKET_HEADER);
pUdsItem->Send((const char*)&sndBuf,sizeof(PACKET_HEADER));
}
void TPeerSocket::RequestPeerToMe(DWORD dwIP,DWORD dwPort) // to do main socket send ptP2S_CONN_REQ to server
{
BUFFER sndBuf;
ZeroMemory(&sndBuf,sizeof(sndBuf));
((P2S_CONN_REQ_PKT*)&sndBuf)->ePacketType = ptP2S_CONN_REQ;
memcpy(((P2S_CONN_REQ_PKT*)&sndBuf)->aProtocolflag,ProtocolFlag,sizeof(ProtocolFlag));
((P2S_CONN_REQ_PKT*)&sndBuf)->dwPacketSize = sizeof(P2S_CONN_REQ_PKT);
((P2S_CONN_REQ_PKT*)&sndBuf)->dwConnToPeerIP=dwIP;
((P2S_CONN_REQ_PKT*)&sndBuf)->dwConnToPort=dwPort;
this->Send((const char*)&sndBuf,sizeof(P2S_CONN_REQ_PKT));
}
void TPeerSocket::Sending(TUdpSocket *pUdpSocket,sockaddr *pToAddr,char* szBuff,const int BuffLen)
{
}
void TPeerSocket::Receiving(TUdpSocket *pUdpSocket,char* szBuff,const int BuffLen)
{
if ( BuffLen<sizeof(PACKET_HEADER) ) return ;
string key;
TUdpSocket *pUdsItem;
BUFFER sndBuf;
PACKET_HEADER *pPacketHeader = (PACKET_HEADER*)szBuff;
TPeerSocket *pPeerSocket = (TPeerSocket*)pUdpSocket;
//Server socket message Process procedure
if ((pPeerSocket->eSocketType & stServer) == stServer)
{
switch ( pPacketHeader->ePacketType )
{
case ptP2S_CONN_REQ: // a peer called RequestPeerToMe active the msg ,server receive conn_req pakket then send the ptS2P_CONN_CMD packet to target peer ( b),cmd the b connect to a . S:0 --> B:0
//to do send ptS2P_CONN_CMD to target peer
ZeroMemory(&sndBuf,sizeof(sndBuf));
((S2P_CONN_CMD_PKT*)&sndBuf)->ePacketType = ptS2P_CONN_CMD;
((S2P_CONN_CMD_PKT*)&sndBuf)->dwReqPeerIP = pPacketHeader->dwFromIp;
((S2P_CONN_CMD_PKT*)&sndBuf)->dwReqPeerPort = pPacketHeader->dwFromPort;
memcpy(((S2P_CONN_CMD_PKT*)&sndBuf)->aProtocolflag,ProtocolFlag,sizeof(ProtocolFlag));
((S2P_CONN_CMD_PKT*)&sndBuf)->dwPacketSize = sizeof(S2P_CONN_CMD_PKT);
pPeerSocket->SendTo(((P2S_CONN_REQ_PKT*)pPacketHeader)->dwConnToPeerIP,((P2S_CONN_REQ_PKT*)pPacketHeader)->dwConnToPort,(const char*)&sndBuf,sizeof(PACKET_HEADER));
break;
case ptP2S_MSG:
break;
}
}
// client socket message process procedure
if ((pPeerSocket->eSocketType & stClient) == stClient)
{
switch ( pPacketHeader->ePacketType )
{
case ptS2P_CONN_CMD:
//the server's packet
if (pPacketHeader->dwFromIp == pPeerSocket->ServerIp && pPacketHeader->dwFromPort == pPeerSocket->ServerPort)
{
pPeerSocket->ConnecdToPeer(((S2P_CONN_CMD_PKT*)pPacketHeader)->dwReqPeerIP,((S2P_CONN_CMD_PKT*)pPacketHeader)->dwFromPort);
}
break;
case ptP2P_CONN_REQ: // a peer calld ConnecdToPeer active the msg
key = IntToStr(pPacketHeader->dwFromIp) + IntToStr(pPacketHeader->dwFromPort);
pUdsItem = new TUdpSocket();
pPeerSocket->m_UdpSocketMap.insert(make_pair(key,pUdsItem)); // add a peer process socket
pUdsItem->ServerIp=pPacketHeader->dwFromIp;
pUdsItem->ServerPort=pPacketHeader->dwFromPort;
pUdsItem->Connect();
ZeroMemory(&sndBuf,sizeof(sndBuf));
((PACKET_HEADER*)&sndBuf)->ePacketType = ptP2P_CONN_FIN;
memcpy(((PACKET_HEADER*)&sndBuf)->aProtocolflag,ProtocolFlag,sizeof(ProtocolFlag));
((PACKET_HEADER*)&sndBuf)->dwPacketSize = sizeof(PACKET_HEADER);
pUdsItem->Send((const char*)&sndBuf,sizeof(PACKET_HEADER));
break;
case ptS2P_MSG:
//the own server's packet
if (pPacketHeader->dwFromIp == pPeerSocket->ServerIp && pPacketHeader->dwFromPort == pPeerSocket->ServerPort)
{
}
break;
}
}
}
TPeerSocket::TPeerSocket(void)
{
OnSending=Sending;
OnReceiving=Receiving;
}
TPeerSocket::~TPeerSocket(void)
{
}
- C++ 开发P2P及时消息发送程序(2)
- C++ 开发P2P及时消息发送程序(1)
- P2P网络通讯程序(C#)
- P2P网络通讯程序(c#)
- p2p服务程序开发
- activemq结合mqtt发送p2p消息
- MFC开发实用教程2:发送自定义消息
- activeMQ之点对点(p2p)发送与接收消息
- socket 消息互发送 程序
- 向其他程序发送消息
- 微信小程序发送模板消息
- 小程序发送template模板消息-小程序支付开发-视频教程
- c#: 向后台发送消息
- 使用C#和MSMQ开发消息处理程序
- [转贴]使用C#和MSMQ开发消息处理程序
- 使用C#和MSMQ开发消息处理程序
- 使用C#和MSMQ开发消息处理程序
- 使用C#和MSMQ开发消息处理程序
- Oracle SQL性能优化技巧大总结
- 调整Oracle应用系统性能的原则和方法
- Oracle10g数据库优化实用心得小结
- Oracle数据库高级复制功能介绍
- 实现Oracle异地数据自动备份的方案
- C++ 开发P2P及时消息发送程序(2)
- Oracle的LOB字段学习
- PLSQL单行函数和组函数详解
- Oracle PL/SQL语言基础
- oracle常用函数
- .NET截取指定长度汉字超出部分以"..."代替
- gpg linux 下简单操作
- Oracle的翻页Sql语句
- PL/SQL基础:阶层查询