网络服务端和客户端添加普通发送模式

This commit is contained in:
~ Alone 2024-11-24 16:30:28 +08:00
parent c09ea42fa9
commit 60aa8883fa
9 changed files with 432 additions and 227 deletions

View File

@ -1,5 +1,6 @@
#include "SocketC.h" #include "SocketC.h"
//初始化socket
bool SocketC::initSocket() bool SocketC::initSocket()
{ {
//³õʼ»¯Ì×½Ó×Ö¿â //³õʼ»¯Ì×½Ó×Ö¿â
@ -23,11 +24,13 @@ bool SocketC::initSocket()
} }
} }
SocketC::SocketC(int bufSize, int modo) //构造
SocketC::SocketC(int mode)
{ {
m_mode = mode;
} }
//析构
SocketC::~SocketC() SocketC::~SocketC()
{ {
if (state == 1) if (state == 1)
@ -36,10 +39,11 @@ SocketC::~SocketC()
} }
} }
//连接到服务器
bool SocketC::Connect(string IP, UINT Prot) bool SocketC::Connect(string IP, UINT Prot)
{ {
if (!initSocket()) if (!initSocket())
{ {//初始化失败
return false; return false;
} }
struct addrinfo* answer, hint; struct addrinfo* answer, hint;
@ -47,27 +51,25 @@ bool SocketC::Connect(string IP, UINT Prot)
ZeroMemory(&hint, sizeof(hint)); ZeroMemory(&hint, sizeof(hint));
hint.ai_family = AF_INET; hint.ai_family = AF_INET;
hint.ai_socktype = SOCK_STREAM; hint.ai_socktype = SOCK_STREAM;
SOCKADDR_IN server_addr; SOCKADDR_IN server_addr;
//解析域名如果传入的IP是域名的情况
if (getaddrinfo(IP.c_str(), NULL, &hint, &answer) == 0) if (getaddrinfo(IP.c_str(), NULL, &hint, &answer) == 0)
{ {
server_addr.sin_family = AF_INET; server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = ((struct sockaddr_in*)(answer->ai_addr))->sin_addr.S_un.S_addr; server_addr.sin_addr.S_un.S_addr = ((struct sockaddr_in*)(answer->ai_addr))->sin_addr.S_un.S_addr;
server_addr.sin_port = htons(Prot); server_addr.sin_port = htons(Prot);
((SOCKADDR_IN*)&hint.ai_addr)->sin_port = htons(Prot); ((SOCKADDR_IN*)&hint.ai_addr)->sin_port = htons(Prot);
//´´½¨Ì×½Ó×Ö //´´½¨Ì×½Ó×Ö
sclient = socket(AF_INET, SOCK_STREAM, 0); sclient = socket(AF_INET, SOCK_STREAM, 0);
//连接到服务器
if (connect(sclient, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) if (connect(sclient, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR)
{ {//连接失败
WSACleanup(); WSACleanup();
return false; return false;
} }
else else
{ {//连接成功创建线程接收数据
state = 1; state = 1;
rec = std::thread((&SocketC::Receive), this); rec = std::thread((&SocketC::Receive), this);
return true; return true;
@ -76,66 +78,85 @@ bool SocketC::Connect(string IP, UINT Prot)
return FALSE; return FALSE;
} }
//接收数据函数
VOID SocketC::Receive() VOID SocketC::Receive()
{ {
char* buff = NULL; char* buff = NULL;
while(state) while(state)
{ {
//开始接收数据
char buf[1024] = { 0 }; char buf[1024] = { 0 };
int len = recv(sclient, buf, 1024, 0); int len = recv(sclient, buf, 1020, 0);
if (len ==SOCKET_ERROR || len == 0) if (len ==SOCKET_ERROR || len == 0)
{ {//服务器关闭了
state = 0; state = 0;
if (Cfunc != NULL) if (Cfunc != NULL)
{ {
Cfunc(); Cfunc();
} }
cout << "·þÎñÆ÷¶Ï¿ªÁ¬½Ó"; //cout << "服务器断开连接";
break; break;
} }
int isStr; if (m_mode == 0)
buff = RecvBuff(buf, len, isStr); {//普通模式直接处理
while (buff)
{
if (Rfunc != NULL) if (Rfunc != NULL)
Rfunc(buf, len);
}
else if (m_mode == 1)
{//处理收到的数据避免出现粘包的情况
int isStr;
buff = RecvBuff(buf, len, isStr);
while (buff)
{ {
if (isStr == 1) if (Rfunc != NULL)
{ {
AES aes; if (isStr == 1)
string str = aes.DecryptionAES(buff, "qwertyuiopasdfgh"); {//如果是字符串先解密
Rfunc((char*)str.c_str(), str.length()); AES aes;
string str = aes.DecryptionAES(buff, "qwertyuiopasdfgh");
Rfunc((char*)str.c_str(), str.length());
}
else
Rfunc(buff, len);
} }
else delete buff;
Rfunc(buff, len); len = 0;
buff = RecvBuff(NULL, len, isStr);
} }
delete buff;
len = 0;
buff = RecvBuff(NULL, len, isStr);
} }
} }
return; return;
} }
//处理收到的数据
char* SocketC::RecvBuff(char* buf, int& len, int& isStr) char* SocketC::RecvBuff(char* buf, int& len, int& isStr)
{ {
char* buff = NULL; char* buff = NULL;
MsgHead* h; MsgHead* h;
lock_guard<std::mutex> guard(msgLock); //lock_guard<std::mutex> guard(msgLock);
//把收到的数据复制到缓冲区
if (len != 0) if (len != 0)
memcpy_s(tmpBuf + bufLen, len, buf, len); memcpy_s(tmpBuf + bufLen, len, buf, len);
bufLen += len; bufLen += len;
//判断缓冲区内的消息长度是否大于消息头
if (bufLen > sizeof(MsgHead)) if (bufLen > sizeof(MsgHead))
{ {//检查消息头是由有问题
h = (MsgHead*)tmpBuf; h = (MsgHead*)tmpBuf;
if (!CheckHead(h))
{//消息头不合规关闭连接
closesocket(sclient);
return NULL;
}
//判断当前消息是否收完
if (bufLen - sizeof(MsgHead) >= h->bufLen) if (bufLen - sizeof(MsgHead) >= h->bufLen)
{ {//当前消息收完了
buff = new char[h->bufLen + 1]; buff = new char[h->bufLen + 1];
ZeroMemory(buff, h->bufLen + 1); ZeroMemory(buff, h->bufLen + 1);
memcpy_s(buff, h->bufLen, tmpBuf + sizeof(MsgHead), h->bufLen); memcpy_s(buff, h->bufLen, tmpBuf + sizeof(MsgHead), h->bufLen);
len = h->bufLen; len = h->bufLen;
isStr = h->isStr; isStr = h->isStr;
bufLen = bufLen - len - sizeof(MsgHead); bufLen = bufLen - len - sizeof(MsgHead);
//缓冲区数据前移
if (bufLen > 0) if (bufLen > 0)
memcpy_s(tmpBuf, bufLen, tmpBuf + sizeof(MsgHead) + len, bufLen); memcpy_s(tmpBuf, bufLen, tmpBuf + sizeof(MsgHead) + len, bufLen);
} }
@ -143,53 +164,104 @@ char* SocketC::RecvBuff(char* buf, int& len, int& isStr)
return buff; return buff;
} }
//检查消息头
int SocketC::SendData(const char* Date, int len, int isStr) BOOL SocketC::CheckHead(MsgHead* h)
{ {
MsgHead h; //消息长度不能大于10000
h.isStr = isStr; if (h->bufLen > 10000)
h.bufLen = len;
time(&h.tm);
string str = to_string(h.tm);
str += to_string(len);
md5 md;
str = md.StringToMD5(str);
memcpy_s(h.token, str.length(), str.c_str(), str.length());
char* buff = new char[sizeof(MsgHead) + len];
memcpy_s(buff, sizeof(MsgHead), &h, sizeof(MsgHead));
memcpy_s(buff + sizeof(MsgHead), len, Date, len);
int lenth = send(sclient, buff, len + sizeof(MsgHead), 0) - sizeof(MsgHead);
delete[] buff;
if (lenth < 0)
{ {
lenth = -1; return FALSE;
} }
return lenth; //机密数据并验证发过来的Token是否正确
string str, str1;
str = to_string(h->tm);
str += to_string(h->bufLen);
md5 md;
str1 = md.StringToMD5(str);
str = h->token;
if (str == str1)
{//token正确验证发送消息的时间
time_t t1;
time(&t1);
if (abs(t1 - h->tm) < 300)
{
return TRUE;
}
}
return FALSE;
} }
//发送数据包
int SocketC::SendData(const char* Data, int len, int isStr)
{
if (Data == NULL)
return -1;
if (m_mode == 0)
{//普通模式直接发送
return send(sclient, Data, len, 0);
}
else if (m_mode == 1)
{//生成token
MsgHead h;
h.isStr = isStr;
h.bufLen = len;
time(&h.tm);
string str = to_string(h.tm);
str += to_string(len);
md5 md;
str = md.StringToMD5(str);
memcpy_s(h.token, str.length(), str.c_str(), str.length());
char* buff = new char[sizeof(MsgHead) + len];
memcpy_s(buff, sizeof(MsgHead), &h, sizeof(MsgHead));
memcpy_s(buff + sizeof(MsgHead), len, Data, len);
//发送数据
int lenth = send(sclient, buff, len + sizeof(MsgHead), 0) - sizeof(MsgHead);
delete[] buff;
if (lenth < 0)
{
lenth = -1;
}
return lenth;
}
}
//发送字符串
BOOL SocketC::SendStr(string str) BOOL SocketC::SendStr(string str)
{ {
if (str == "") if (str == "")
return FALSE; return FALSE;
AES aes; if (m_mode == 0)
string sendStr = aes.EncryptionAES(str, "qwertyuiopasdfgh"); {//普通模式直接发送
if (-1 == SendData(sendStr.c_str(), sendStr.length(), 1)) if (send(sclient, str.c_str(), str.length(), 0) == -1)
{ {
return FALSE; return FALSE;
}
}
else if (m_mode == 1)
{//加密发送的字符串并发送
AES aes;
string sendStr = aes.EncryptionAES(str, "qwertyuiopasdfgh");
if (-1 == SendData(sendStr.c_str(), sendStr.length(), 1))
{
return FALSE;
}
} }
return TRUE; return TRUE;
} }
//设置接收数据的回调函数
VOID SocketC::SetRecvFunc(function<VOID(char*, int)> fun) VOID SocketC::SetRecvFunc(function<VOID(char*, int)> fun)
{ {
Rfunc = fun; Rfunc = fun;
} }
//设置断开连接的回调函数
VOID SocketC::SetCloseFunc(function<VOID()> fun) VOID SocketC::SetCloseFunc(function<VOID()> fun)
{ {
Cfunc = fun; Cfunc = fun;
} }
//断开连接
void SocketC::Close() void SocketC::Close()
{ {
if (state != 0) if (state != 0)

View File

@ -23,26 +23,26 @@ private:
char token[34] = { 0 }; char token[34] = { 0 };
}; };
char tmpBuf[10240] = { 0 }; char tmpBuf[10240] = { 0 }; //缓冲区
int bufLen = 0; int bufLen = 0; //当前接收了多长的数据
SOCKET sclient = 0; SOCKET sclient = 0; //socket客户端
BOOL state = 0; BOOL state = 0; //当前状态
std::thread rec; int m_mode; //当前工作的模式
std::mutex msgLock; std::thread rec; //用来接数据的收线程
function<VOID(char*, int)> Rfunc = NULL; function<VOID(char*, int)> Rfunc = NULL; //接收到了数据的回调函数
function<VOID()> Cfunc = NULL; function<VOID()> Cfunc = NULL; //断开连接的回调函数
bool initSocket(); bool initSocket(); //初始化socket
VOID Receive(); VOID Receive(); //接收数据函数
char* RecvBuff(char* buf, int& len, int& isStr); char* RecvBuff(char* buf, int& len, int& isStr); //处理收到的数据
BOOL CheckHead(MsgHead* h); //检查消息头
public: public:
SocketC(int bufSize = 4096, int modo = 0); SocketC(int mode = 0); //构造
~SocketC(); ~SocketC(); //析构
bool Connect(string IP, UINT Prot); bool Connect(string IP, UINT Prot); //连接到服务器
int SendData(const char* Date, int len, int isStr = 0); int SendData(const char* Date, int len, int isStr = 0); //发送数据包
BOOL SendStr(string str); BOOL SendStr(string str); //发送字符串
VOID SetRecvFunc(function<VOID(char*, int)> fun); VOID SetRecvFunc(function<VOID(char*, int)> fun); //设置接收数据的回调函数
VOID SetCloseFunc(function<VOID()> fun); VOID SetCloseFunc(function<VOID()> fun); //设置断开连接的回调函数
void Close(); void Close(); //断开连接
}; };

View File

@ -6,7 +6,7 @@ using namespace std;
SocketC c; SocketC c(1);
int flag = 1; int flag = 1;
int myName = 0; int myName = 0;

View File

@ -15,33 +15,45 @@ DWORD WINAPI SocketS::ThreadProc(LPVOID lpParameter)
while (server->g_flag) while (server->g_flag)
{//获取完成端口的数据 {//获取完成端口的数据
BOOL bFlag = GetQueuedCompletionStatus(port, &len, &index, &lpOverlapped, INFINITE); BOOL bFlag = GetQueuedCompletionStatus(port, &len, &index, &lpOverlapped, INFINITE);
server->Lock.lock(); //server->Lock.lock();
clienInfo* clien = &server->ClienMap[index]; clienInfo* clien = &server->ClienMap[index];
if (bFlag == TRUE && len > 0) if (bFlag == TRUE && len > 0)
{// 接收到客户端消息 {// 接收到客户端消息
clien->Rbuflen += len; if (server->m_mode == 0)
DOSTART {//普通模式
if (clien->Rbuflen < sizeof(MsgHead)) if (server->Rfunc != NULL)
break; {
if (clien->Rbuflen - sizeof(MsgHead) < clien->h.bufLen) server->Rfunc(index, clien->buff, len);
break; }
if (clien->buff == NULL) ZeroMemory(clien->buff, sizeof(clien->buff));
break;
if (server->Rfunc == NULL)
break;
if (clien->h.isStr == 1)
{
AES aes;
string str = aes.DecryptionAES(clien->buff, "qwertyuiopasdfgh");
server->Rfunc(index, (char*)str.c_str(), str.length());
}
else
server->Rfunc(index, clien->buff, len);
ZeroMemory(clien->buff,sizeof(clien->buff));
clien->Rbuflen = 0;
DOEND
server->PostRecv(index); // 对自己投递接收 server->PostRecv(index); // 对自己投递接收
}
else if (server->m_mode == 1)
{
clien->Rbuflen += len;
DOSTART
if (clien->Rbuflen < sizeof(MsgHead))
break;
if (clien->Rbuflen - sizeof(MsgHead) < clien->h.bufLen)
break;
if (clien->buff == NULL)
break;
if (server->Rfunc == NULL)
break;
if (clien->h.isStr == 1)
{
AES aes;
string str = aes.DecryptionAES(clien->buff, "qwertyuiopasdfgh");
server->Rfunc(index, (char*)str.c_str(), str.length());
}
else
server->Rfunc(index, clien->buff, len);
ZeroMemory(clien->buff, sizeof(clien->buff));
clien->Rbuflen = 0;
DOEND
server->PostRecv(index); // 对自己投递接收
}
} }
else else
{//客户端关闭 {//客户端关闭
@ -52,15 +64,22 @@ DWORD WINAPI SocketS::ThreadProc(LPVOID lpParameter)
server->CloseClien(index); server->CloseClien(index);
} }
server->Lock.unlock(); //server->Lock.unlock();
} }
server->Count--; server->Count--;
return 0; return 0;
} }
//构造
SocketS::SocketS() SocketS::SocketS(int mode)
{ {
m_mode = mode;
}
//析构
SocketS::~SocketS()
{
Close();
} }
//投递消息 //投递消息
@ -68,28 +87,37 @@ VOID SocketS::PostRecv(int index)
{ {
WSABUF wsabuf; WSABUF wsabuf;
clienInfo* clien = &ClienMap[index]; clienInfo* clien = &ClienMap[index];
if (clien->Rbuflen < sizeof(MsgHead)) if (m_mode == 0)
{//收到的消息还没消息头长
wsabuf.buf = (char*)&clien->h + clien->Rbuflen;
wsabuf.len = sizeof(MsgHead) - clien->Rbuflen;
}
else
{ {
if (clien->Rbuflen == sizeof(MsgHead)) wsabuf.buf = clien->buff;
{//刚接收完消息头 wsabuf.len = 1020;
if (!CheckHead(&clien->h))
{//消息头有问题
CloseClien(index);
return;
}
}
wsabuf.buf = clien->buff + (clien->Rbuflen - sizeof(MsgHead));
//剩余消息如果大于1020那么分块接收消息
if (clien->h.bufLen - clien->Rbuflen + sizeof(MsgHead) > 1020)
wsabuf.len = 1020;
else
wsabuf.len = clien->h.bufLen - clien->Rbuflen + sizeof(MsgHead);
} }
else if (m_mode == 1)
{
if (clien->Rbuflen < sizeof(MsgHead))
{//收到的消息还没消息头长
wsabuf.buf = (char*)&clien->h + clien->Rbuflen;
wsabuf.len = sizeof(MsgHead) - clien->Rbuflen;
}
else
{
if (clien->Rbuflen == sizeof(MsgHead))
{//刚接收完消息头
if (!CheckHead(&clien->h))
{//消息头有问题
CloseClien(index);
return;
}
}
wsabuf.buf = clien->buff + (clien->Rbuflen - sizeof(MsgHead));
//剩余消息如果大于1020那么分块接收消息
if (clien->h.bufLen - clien->Rbuflen + sizeof(MsgHead) > 1020)
wsabuf.len = 1020;
else
wsabuf.len = clien->h.bufLen - clien->Rbuflen + sizeof(MsgHead);
}
}
//让完成端口继续接收数据 //让完成端口继续接收数据
DWORD dwRecvCount = wsabuf.len; DWORD dwRecvCount = wsabuf.len;
DWORD dwFlag = 0; DWORD dwFlag = 0;
@ -217,6 +245,8 @@ BOOL SocketS::Creat(int Prot)
//关闭服务端 //关闭服务端
void SocketS::Close() void SocketS::Close()
{//清除客户端 {//清除客户端
if (g_flag == 0)
return;
g_flag = 0; g_flag = 0;
Lock.lock(); Lock.lock();
for (auto i = ClienMap.begin(); i != ClienMap.end(); i++) for (auto i = ClienMap.begin(); i != ClienMap.end(); i++)
@ -269,29 +299,40 @@ VOID SocketS::GetClienName(int index, string& IP, int& Prot)
//发送数据包 //发送数据包
int SocketS::SendData(int index,const char* buf, int len, int isStr) int SocketS::SendData(int index,const char* buf, int len, int isStr)
{//创建消息头生成token {
MsgHead h; if (buf == NULL)
h.bufLen = len; return -1;
h.isStr = isStr; if (m_mode == 0)
time(&h.tm); {//普通模式
string str = to_string(h.tm); return PostSend(index, buf, len);
str += to_string(len);
md5 md;
str = md.StringToMD5(str);
memcpy_s(h.token, str.length(), str.c_str(), str.length());
//合并消息头和消息体
char* buff = new char[sizeof(MsgHead) + len];
memcpy_s(buff, sizeof(MsgHead), &h, sizeof(MsgHead));
memcpy_s(buff + sizeof(MsgHead), len, buf, len);
//发送消息
int lenth = PostSend(index, buff, len + sizeof(MsgHead)) - sizeof(MsgHead);
delete[] buff;
if (lenth < 0)
{//消息发送失败
CloseClien(index);
lenth = -1;
} }
return lenth; else if (m_mode == 1)
{
//创建消息头生成token
MsgHead h;
h.bufLen = len;
h.isStr = isStr;
time(&h.tm);
string str = to_string(h.tm);
str += to_string(len);
md5 md;
str = md.StringToMD5(str);
memcpy_s(h.token, str.length(), str.c_str(), str.length());
//合并消息头和消息体
char* buff = new char[sizeof(MsgHead) + len];
memcpy_s(buff, sizeof(MsgHead), &h, sizeof(MsgHead));
memcpy_s(buff + sizeof(MsgHead), len, buf, len);
//发送消息
int lenth = PostSend(index, buff, len + sizeof(MsgHead)) - sizeof(MsgHead);
delete[] buff;
if (lenth < 0)
{//消息发送失败
CloseClien(index);
lenth = -1;
}
return lenth;
}
return -1;
} }
//发送字符串 //发送字符串
@ -299,13 +340,23 @@ BOOL SocketS::SendStr(int index, string str)
{//判断消息不能为空 {//判断消息不能为空
if (str == "") if (str == "")
return FALSE; return FALSE;
//加密字符串 if (m_mode == 0)
AES aes; {//普通模式
string sendStr = aes.EncryptionAES(str,"qwertyuiopasdfgh"); if (PostSend(index, str.c_str(), str.length()) == -1)
//发送消息 {
if (-1 == SendData(index, sendStr.c_str(), sendStr.length(), 1)) return FALSE;
{//消息发送失败 }
return FALSE; }
else if (m_mode == 1)
{
//加密字符串
AES aes;
string sendStr = aes.EncryptionAES(str, "qwertyuiopasdfgh");
//发送消息
if (-1 == SendData(index, sendStr.c_str(), sendStr.length(), 1))
{//消息发送失败
return FALSE;
}
} }
return TRUE; return TRUE;
} }

View File

@ -45,6 +45,7 @@ private:
std::thread *ListenClien; //监听线程 std::thread *ListenClien; //监听线程
int Count = 0; //工作者线程多少个 int Count = 0; //工作者线程多少个
mutex Lock; //线程锁 mutex Lock; //线程锁
int m_mode; //当前工作的模式
function<VOID(int,char*,int)> Rfunc = NULL; //接收数据的回调函数 function<VOID(int,char*,int)> Rfunc = NULL; //接收数据的回调函数
function<VOID(int)> Cfunc = NULL; //客户端关闭的回调函数 function<VOID(int)> Cfunc = NULL; //客户端关闭的回调函数
@ -55,7 +56,8 @@ private:
VOID Listens(); //监听消息函数 VOID Listens(); //监听消息函数
public: public:
SocketS(); //¹¹Ôì SocketS(int mode = 0); //构造
~SocketS(); //构造
BOOL Creat(int Prot); //创建服务端 BOOL Creat(int Prot); //创建服务端
void Close(); //关闭服务端 void Close(); //关闭服务端
VOID SetRecvFunc(function<VOID(int, char*, int)> fun); //设置接收消息的回调函数 VOID SetRecvFunc(function<VOID(int, char*, int)> fun); //设置接收消息的回调函数

View File

@ -29,7 +29,7 @@ struct msgInfo
std::map<int/*name*/, int/*index*/> clienMap; std::map<int/*name*/, int/*index*/> clienMap;
std::map<int/*index*/, int/*name*/> clienIndex; std::map<int/*index*/, int/*name*/> clienIndex;
SocketS s; SocketS s(1);
int cont = 0; int cont = 0;
VOID closeFunc(int index) VOID closeFunc(int index)
{ {
@ -52,8 +52,8 @@ VOID recvFunc(int index, char* buf, int len)
int main(void) int main(void)
{ {
//s.SetRecvFunc([&tt](SocketS::msgInfo info) {return tt.ppp(info); }); //s.SetRecvFunc([&tt](SocketS::msgInfo info) {return tt.ppp(info); });
s.Creat(6666); //s.Creat(6666);
s.Close(); //s.Close();
s.SetCloseFunc(closeFunc); s.SetCloseFunc(closeFunc);
s.SetRecvFunc(recvFunc); s.SetRecvFunc(recvFunc);

View File

@ -1,5 +1,6 @@
#include "SocketC.h" #include "SocketC.h"
//初始化socket
bool SocketC::initSocket() bool SocketC::initSocket()
{ {
//初始化套接字库 //初始化套接字库
@ -23,11 +24,13 @@ bool SocketC::initSocket()
} }
} }
SocketC::SocketC(int bufSize, int modo) //构造
SocketC::SocketC(int mode)
{ {
m_mode = mode;
} }
//析构
SocketC::~SocketC() SocketC::~SocketC()
{ {
if (state == 1) if (state == 1)
@ -36,10 +39,11 @@ SocketC::~SocketC()
} }
} }
//连接到服务器
bool SocketC::Connect(string IP, UINT Prot) bool SocketC::Connect(string IP, UINT Prot)
{ {
if (!initSocket()) if (!initSocket())
{ {//初始化失败
return false; return false;
} }
struct addrinfo* answer, hint; struct addrinfo* answer, hint;
@ -47,27 +51,25 @@ bool SocketC::Connect(string IP, UINT Prot)
ZeroMemory(&hint, sizeof(hint)); ZeroMemory(&hint, sizeof(hint));
hint.ai_family = AF_INET; hint.ai_family = AF_INET;
hint.ai_socktype = SOCK_STREAM; hint.ai_socktype = SOCK_STREAM;
SOCKADDR_IN server_addr; SOCKADDR_IN server_addr;
//解析域名如果传入的IP是域名的情况
if (getaddrinfo(IP.c_str(), NULL, &hint, &answer) == 0) if (getaddrinfo(IP.c_str(), NULL, &hint, &answer) == 0)
{ {
server_addr.sin_family = AF_INET; server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = ((struct sockaddr_in*)(answer->ai_addr))->sin_addr.S_un.S_addr; server_addr.sin_addr.S_un.S_addr = ((struct sockaddr_in*)(answer->ai_addr))->sin_addr.S_un.S_addr;
server_addr.sin_port = htons(Prot); server_addr.sin_port = htons(Prot);
((SOCKADDR_IN*)&hint.ai_addr)->sin_port = htons(Prot); ((SOCKADDR_IN*)&hint.ai_addr)->sin_port = htons(Prot);
//创建套接字 //创建套接字
sclient = socket(AF_INET, SOCK_STREAM, 0); sclient = socket(AF_INET, SOCK_STREAM, 0);
//连接到服务器
if (connect(sclient, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) if (connect(sclient, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR)
{ {//连接失败
WSACleanup(); WSACleanup();
return false; return false;
} }
else else
{ {//连接成功创建线程接收数据
state = 1; state = 1;
rec = std::thread((&SocketC::Receive), this); rec = std::thread((&SocketC::Receive), this);
return true; return true;
@ -76,15 +78,17 @@ bool SocketC::Connect(string IP, UINT Prot)
return FALSE; return FALSE;
} }
//接收数据函数
VOID SocketC::Receive() VOID SocketC::Receive()
{ {
char* buff = NULL; char* buff = NULL;
while(state) while(state)
{ {
//开始接收数据
char buf[1024] = { 0 }; char buf[1024] = { 0 };
int len = recv(sclient, buf, 1024, 0); int len = recv(sclient, buf, 1020, 0);
if (len ==SOCKET_ERROR || len == 0) if (len ==SOCKET_ERROR || len == 0)
{ {//服务器关闭了
state = 0; state = 0;
if (Cfunc != NULL) if (Cfunc != NULL)
{ {
@ -93,49 +97,66 @@ VOID SocketC::Receive()
//cout << "服务器断开连接"; //cout << "服务器断开连接";
break; break;
} }
int isStr; if (m_mode == 0)
buff = RecvBuff(buf, len, isStr); {//普通模式直接处理
while (buff)
{
if (Rfunc != NULL) if (Rfunc != NULL)
Rfunc(buf, len);
}
else if (m_mode == 1)
{//处理收到的数据避免出现粘包的情况
int isStr;
buff = RecvBuff(buf, len, isStr);
while (buff)
{ {
if (isStr == 1) if (Rfunc != NULL)
{ {
AES aes; if (isStr == 1)
string str = aes.DecryptionAES(buff, "qwertyuiopasdfgh"); {//如果是字符串先解密
Rfunc((char*)str.c_str(), str.length()); AES aes;
string str = aes.DecryptionAES(buff, "qwertyuiopasdfgh");
Rfunc((char*)str.c_str(), str.length());
}
else
Rfunc(buff, len);
} }
else delete buff;
Rfunc(buff, len); len = 0;
buff = RecvBuff(NULL, len, isStr);
} }
delete buff;
len = 0;
buff = RecvBuff(NULL, len, isStr);
} }
} }
return; return;
} }
//处理收到的数据
char* SocketC::RecvBuff(char* buf, int& len, int& isStr) char* SocketC::RecvBuff(char* buf, int& len, int& isStr)
{ {
char* buff = NULL; char* buff = NULL;
MsgHead* h; MsgHead* h;
lock_guard<std::mutex> guard(msgLock); //lock_guard<std::mutex> guard(msgLock);
//把收到的数据复制到缓冲区
if (len != 0) if (len != 0)
memcpy_s(tmpBuf + bufLen, len, buf, len); memcpy_s(tmpBuf + bufLen, len, buf, len);
bufLen += len; bufLen += len;
//判断缓冲区内的消息长度是否大于消息头
if (bufLen > sizeof(MsgHead)) if (bufLen > sizeof(MsgHead))
{ {//检查消息头是由有问题
h = (MsgHead*)tmpBuf; h = (MsgHead*)tmpBuf;
if (!CheckHead(h))
{//消息头不合规关闭连接
closesocket(sclient);
return NULL;
}
//判断当前消息是否收完
if (bufLen - sizeof(MsgHead) >= h->bufLen) if (bufLen - sizeof(MsgHead) >= h->bufLen)
{ {//当前消息收完了
buff = new char[h->bufLen + 1]; buff = new char[h->bufLen + 1];
ZeroMemory(buff, h->bufLen + 1); ZeroMemory(buff, h->bufLen + 1);
memcpy_s(buff, h->bufLen, tmpBuf + sizeof(MsgHead), h->bufLen); memcpy_s(buff, h->bufLen, tmpBuf + sizeof(MsgHead), h->bufLen);
len = h->bufLen; len = h->bufLen;
isStr = h->isStr; isStr = h->isStr;
bufLen = bufLen - len - sizeof(MsgHead); bufLen = bufLen - len - sizeof(MsgHead);
//缓冲区数据前移
if (bufLen > 0) if (bufLen > 0)
memcpy_s(tmpBuf, bufLen, tmpBuf + sizeof(MsgHead) + len, bufLen); memcpy_s(tmpBuf, bufLen, tmpBuf + sizeof(MsgHead) + len, bufLen);
} }
@ -143,53 +164,104 @@ char* SocketC::RecvBuff(char* buf, int& len, int& isStr)
return buff; return buff;
} }
//检查消息头
int SocketC::SendData(const char* Date, int len, int isStr) BOOL SocketC::CheckHead(MsgHead* h)
{ {
MsgHead h; //消息长度不能大于10000
h.isStr = isStr; if (h->bufLen > 10000)
h.bufLen = len;
time(&h.tm);
string str = to_string(h.tm);
str += to_string(len);
md5 md;
str = md.StringToMD5(str);
memcpy_s(h.token, str.length(), str.c_str(), str.length());
char* buff = new char[sizeof(MsgHead) + len];
memcpy_s(buff, sizeof(MsgHead), &h, sizeof(MsgHead));
memcpy_s(buff + sizeof(MsgHead), len, Date, len);
int lenth = send(sclient, buff, len + sizeof(MsgHead), 0) - sizeof(MsgHead);
delete[] buff;
if (lenth < 0)
{ {
lenth = -1; return FALSE;
} }
return lenth; //机密数据并验证发过来的Token是否正确
string str, str1;
str = to_string(h->tm);
str += to_string(h->bufLen);
md5 md;
str1 = md.StringToMD5(str);
str = h->token;
if (str == str1)
{//token正确验证发送消息的时间
time_t t1;
time(&t1);
if (abs(t1 - h->tm) < 300)
{
return TRUE;
}
}
return FALSE;
} }
//发送数据包
int SocketC::SendData(const char* Data, int len, int isStr)
{
if (Data == NULL)
return -1;
if (m_mode == 0)
{//普通模式直接发送
return send(sclient, Data, len, 0);
}
else if (m_mode == 1)
{//生成token
MsgHead h;
h.isStr = isStr;
h.bufLen = len;
time(&h.tm);
string str = to_string(h.tm);
str += to_string(len);
md5 md;
str = md.StringToMD5(str);
memcpy_s(h.token, str.length(), str.c_str(), str.length());
char* buff = new char[sizeof(MsgHead) + len];
memcpy_s(buff, sizeof(MsgHead), &h, sizeof(MsgHead));
memcpy_s(buff + sizeof(MsgHead), len, Data, len);
//发送数据
int lenth = send(sclient, buff, len + sizeof(MsgHead), 0) - sizeof(MsgHead);
delete[] buff;
if (lenth < 0)
{
lenth = -1;
}
return lenth;
}
}
//发送字符串
BOOL SocketC::SendStr(string str) BOOL SocketC::SendStr(string str)
{ {
if (str == "") if (str == "")
return FALSE; return FALSE;
AES aes; if (m_mode == 0)
string sendStr = aes.EncryptionAES(str, "qwertyuiopasdfgh"); {//普通模式直接发送
if (-1 == SendData(sendStr.c_str(), sendStr.length(), 1)) if (send(sclient, str.c_str(), str.length(), 0) == -1)
{ {
return FALSE; return FALSE;
}
}
else if (m_mode == 1)
{//加密发送的字符串并发送
AES aes;
string sendStr = aes.EncryptionAES(str, "qwertyuiopasdfgh");
if (-1 == SendData(sendStr.c_str(), sendStr.length(), 1))
{
return FALSE;
}
} }
return TRUE; return TRUE;
} }
//设置接收数据的回调函数
VOID SocketC::SetRecvFunc(function<VOID(char*, int)> fun) VOID SocketC::SetRecvFunc(function<VOID(char*, int)> fun)
{ {
Rfunc = fun; Rfunc = fun;
} }
//设置断开连接的回调函数
VOID SocketC::SetCloseFunc(function<VOID()> fun) VOID SocketC::SetCloseFunc(function<VOID()> fun)
{ {
Cfunc = fun; Cfunc = fun;
} }
//断开连接
void SocketC::Close() void SocketC::Close()
{ {
if (state != 0) if (state != 0)

View File

@ -1,8 +1,16 @@
#pragma once #pragma once
#include "pub.h" #include<iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <thread>
#include <mutex>
#include <functional>
#include "md5.h" #include "md5.h"
#include "AES.h" #include "AES.h"
#pragma comment(lib,"ws2_32.lib")
using namespace std;
class SocketC class SocketC
{ {
private: private:
@ -15,26 +23,26 @@ private:
char token[34] = { 0 }; char token[34] = { 0 };
}; };
char tmpBuf[10240] = { 0 }; char tmpBuf[10240] = { 0 }; //缓冲区
int bufLen = 0; int bufLen = 0; //当前接收了多长的数据
SOCKET sclient = 0; SOCKET sclient = 0; //socket客户端
BOOL state = 0; BOOL state = 0; //当前状态
std::thread rec; int m_mode; //当前工作的模式
std::mutex msgLock; std::thread rec; //用来接数据的收线程
function<VOID(char*, int)> Rfunc = NULL; function<VOID(char*, int)> Rfunc = NULL; //接收到了数据的回调函数
function<VOID()> Cfunc = NULL; function<VOID()> Cfunc = NULL; //断开连接的回调函数
bool initSocket(); bool initSocket(); //初始化socket
VOID Receive(); VOID Receive(); //接收数据函数
char* RecvBuff(char* buf, int& len, int& isStr); char* RecvBuff(char* buf, int& len, int& isStr); //处理收到的数据
BOOL CheckHead(MsgHead* h); //检查消息头
public: public:
SocketC(int bufSize = 4096, int modo = 0); SocketC(int mode = 0); //构造
~SocketC(); ~SocketC(); //析构
bool Connect(string IP, UINT Prot); bool Connect(string IP, UINT Prot); //连接到服务器
int SendData(const char* Date, int len, int isStr = 0); int SendData(const char* Date, int len, int isStr = 0); //发送数据包
BOOL SendStr(string str); BOOL SendStr(string str); //发送字符串
VOID SetRecvFunc(function<VOID(char*, int)> fun); VOID SetRecvFunc(function<VOID(char*, int)> fun); //设置接收数据的回调函数
VOID SetCloseFunc(function<VOID()> fun); VOID SetCloseFunc(function<VOID()> fun); //设置断开连接的回调函数
void Close(); void Close(); //断开连接
}; };

View File

@ -3,7 +3,7 @@
#include "Json.h" #include "Json.h"
#include "SocketC.h" #include "SocketC.h"
SocketC tcpc; SocketC tcpc(1);
char* U8ToUnicode(char* szU8) char* U8ToUnicode(char* szU8)
{ {