#include "Worker.h"
#include "../public/CRC32.h"
#include "../public/MD5.h"
#include <string>
#include <regex>
using namespace std;
CWorker* CWorker::m_worker;
DWORD WINAPI CWorker::RecvThreadProc(LPVOID lparam)
{
CWorker* pThis = (CWorker*)lparam;
Msg recvMsg = { 0 };
int msglen = sizeof(Msg);
char szAddress[32] = { 0 };
unsigned int nPort = 0;
while (!(pThis->m_bExit))
{
// 此处可以改进为使用 接收的消息队列
// 其中一个线程作为接收,放入消息队里中,其中一个线程不停的在消息队列中获取消息,并进行处理!!!
ZeroMemory(&recvMsg, msglen);
ZeroMemory(szAddress, sizeof(szAddress));
int iread = pThis->m_sock->ReceiveFrom(&recvMsg, msglen, szAddress, nPort);
if (iread <= 0 || iread != msglen) // recv error
{
//printf("recvfrom failed : %d\n", GetLastError());
continue;
}
// CRC差错检测
if (recvMsg.head.CRC32 != ::GetCRC32(recvMsg.content.szMsg,recvMsg.head.nContentLen))
continue;
/******************************************************/
/* 根据数据包消息头进行分发处理 */
/*******************************************************/
switch (recvMsg.head.sCmd)
{
case CMDP2PMESSAGEACK:// P2P消息确认包的处理,来自客户端
{
pThis->m_bReplyACK = true;
printf("Recv message ack from %s:%ld\n", szAddress, nPort);
break;
}
case CMDP2PMESSAGE:// 接收到P2P消息的处理,来自客户端
{
printf("Recv Message from %s[%s:%d] -> %s\n", recvMsg.content.p2pmesssage.username,
szAddress, nPort, recvMsg.content.p2pmesssage.message);
ZeroMemory(&recvMsg, msglen);
recvMsg.head.sCmd = CMDP2PMESSAGEACK;
recvMsg.head.nContentLen = 0;
recvMsg.head.CRC32 = ::GetCRC32(recvMsg.content.szMsg, recvMsg.head.nContentLen);
pThis->m_sock->SendTo(&recvMsg, msglen, nPort, szAddress);
printf("Send a Message ACK to %s[%s:%d]\n", recvMsg.content.p2pmesssage.username, szAddress, nPort);
break;
}
case CMDP2PGETALLUSERACK:// getu 获取所有用户信息回复包,来自服务端
{
pThis->m_bReplyACK = true;
printf("Recv getu ack from server\n");
ZeroMemory(&recvMsg, sizeof(Msg));
if (!pThis->OnCmdRecvFrom(recvMsg, CMDP2PGETUSERCNT,pThis->m_ServerIP, pThis->m_serverPort))
{
printf("Get user count from server timeout...\n");
continue;
}
int usercount = recvMsg.content.usercount;
printf("Have %d users logined server\n", usercount);
// 3、开始逐条接收(可能会有丢包出现,可以记录是哪个包丢失,然后进行重新申请)
int nCntRecved = 0;
int nodelen = sizeof(stUserListNode);
pThis->m_UserList.clear();
for (int i = 0; i < usercount; i++)
{
stUserListNode *node = new stUserListNode;
if (!pThis->OnGetUsersRecvFrom(node, nodelen, pThis->m_ServerIP, pThis->m_serverPort))
{
printf("Get user info from server timeout...\n");
continue;
}
pThis->m_UserList.push_back(node);
in_addr tmp;
tmp.S_un.S_addr = htonl(node->ip);
printf("Username:%s\nUserIP:%s\nUserPort:%d\n\n", node->userName, inet_ntoa(tmp), node->port);
nCntRecved++;
}
printf("Has received %d users form server\n", nCntRecved);
break;
}
case CMDP2PTRANSACK:// 主动请求打洞确认包,来自服务端
{
pThis->m_bReplyACK = true;
printf("Recv p2ptransACK from server\n");
break;
}
case CMDREQUESTP2P:// 对方的打洞请求,来自服务端的转发
{
printf("Recv P2P request from %s\n",recvMsg.content.servtransmsg.userName);
printf("Send P2P request ACK to %s\n", recvMsg.content.servtransmsg.userName);
unsigned int toIP = recvMsg.content.servtransmsg.nIP;
unsigned short toPort = recvMsg.content.servtransmsg.nPort;
ZeroMemory(&recvMsg, msglen);
recvMsg.head.sCmd = CMDREQUESTP2PACK;
recvMsg.head.nContentLen = 0;
recvMsg.head.CRC32 = ::GetCRC32(recvMsg.content.szMsg, recvMsg.head.nContentLen);
pThis->m_sock->SendTo2(&recvMsg, msglen, toPort, toIP);
break;
}
case CMDREQUESTP2PACK:// 对方发来的打洞消息,忽略,来自客户端
{
// do nothing
printf("Recv P2P burrow ACK from %s:%d\n", szAddress, nPort);
break;
}
case CMDLOGOUTACK:// 确认下线消息
{
pThis->m_bReplyACK = true;
break;
}
case CMDHEARTMSG:// 心跳包消息
{
//printf("recv one heart packet \n");
ZeroMemory(&recvMsg, msglen);
strcpy_s(recvMsg.content.heartmessage.userName, pThis->m_UserName);
recvMsg.head.sCmd = CMDHEARTMSGACK;
recvMsg.head.nContentLen = strlen(pThis->m_UserName);
recvMsg.head.CRC32 = ::GetCRC32(recvMsg.content.szMsg, recvMsg.head.nContentLen);
pThis->m_sock->SendTo(&recvMsg, msglen, pThis->m_serverPort, pThis->m_ServerIP);
//printf("reply heart ack to server\n");
break;
}
}
}
printf("Worker Thread exit...\n");
return 0;
}
bool CWorker::InitNetEnvironment(int nPort/*=0*/)
{
if (!m_sock->Create(nPort, SOCK_DGRAM))
return false;
return true;
}
bool CWorker::IsIP(char* ip)
{
regex pattern("\\b([1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4])\\.([0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4])\\.([0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4])\\.([0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4])\\b");
return regex_match(ip, pattern);
}
bool CWorker::CheckPackage(Msg msg)
{
if (msg.head.CRC32 == ::GetCRC32(msg.content.szMsg, msg.head.nContentLen))
return true;
return false;
}
bool CWorker::OnLogin()
{
printf("\n");
do
{
ZeroMemory(m_ServerIP, sizeof(m_ServerIP));
printf("Please input server ip:");
scanf_s("%s", m_ServerIP, sizeof(m_ServerIP));
} while (!IsIP(m_ServerIP));
printf("Please input your name:");
ZeroMemory(m_UserName, USERNAMELEN);
scanf_s("%s", m_UserName, sizeof(m_UserName));
printf("Please input your password:");
ZeroMemory(m_UserPwd, USERPASSWORDLEN);
scanf_s("%s", m_UserPwd, sizeof(m_UserPwd));
return ConnectToServer(m_ServerIP, m_UserName, m_UserPwd);
}
bool CWorker::ConnectToServer(char* serverip, char* szName, char* szPwd, int max_time)
{
// 1、对密码进行MD5加密处理
string check = szName + string("#") + ::md5(szPwd);
MsgContent msgcontent = { 0 };
strcpy(msgcontent.loginmember.userName, szName);
strcpy(msgcontent.loginmember.check, check.c_str());
// 2、封装数据包,进行CRC32校验
Msg msg = { 0 };
msg.head.sCmd = CMDLOGIN;
msg.head.nContentLen = strlen(msgcontent.szMsg);
msg.head.CRC32 = GetCRC32(msgcontent.szMsg, msg.head.nContentLen);
memcpy(&msg.content.loginmember, &msgcontent, sizeof(stLoginMessage));
// 3、发送登录数据包 登录服务器
printf("begin to connect server...\n");
if(!SendtoServer(msg,CMDLOGINACK,m_ServerIP,m_serverPort))
{
printf("connect server timeout...\n");
return false;
}
// 4、登录服务器成功,开始接收在线端用户数量
ZeroMemory(&msg, sizeof(Msg));
int usercount = 0;
int iread = 0;
if (!OnCmdRecvFrom(msg, CMDP2PGETUSERCNT, m_ServerIP, m_serverPort))
{
printf("Get user count from server timeout...\n");
return false;
}
usercount = msg.content.usercount;
printf("Have %d users logined server\n", usercount);
// 5、接收在线用户信息
int nCntRecved = 0;
int nodelen = sizeof(stUserListNode);
m_UserList.clear();
for (int i = 0; i < usercount; i++)
{
stUserListNode *node = new stUserListNode;
if (!OnGetUsersRecvFrom(node, nodelen, m_ServerIP, m_serverPort))
{
printf("Get user info from server timeout...\n");
continue;
}
m_UserList.push_back(node);
in_addr tmp;
tmp.S_un.S_addr = htonl(node->ip);
printf("Username:%s\nUserIP:%s\nUserPort:%d\n\n", node->userName, inet_ntoa(tmp), node->port);
nCntRecved++;
}
printf("Has received %d users form server\n", nCntRecved);
m_hThread = CreateThread(NULL, NULL, RecvThreadProc, m_worker, NULL, NULL);
if (m_hThread == INVALID_HANDLE_VALUE)
{
printf("CreateThread Failed!\n");
return false;
}
return true;
}
bool CWorker::OnGetU()
- 1
- 2
前往页