网络服务端和客户端添加普通发送模式
This commit is contained in:
parent
c09ea42fa9
commit
60aa8883fa
@ -1,5 +1,6 @@
|
||||
#include "SocketC.h"
|
||||
|
||||
//初始化socket
|
||||
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()
|
||||
{
|
||||
if (state == 1)
|
||||
@ -36,10 +39,11 @@ SocketC::~SocketC()
|
||||
}
|
||||
}
|
||||
|
||||
//连接到服务器
|
||||
bool SocketC::Connect(string IP, UINT Prot)
|
||||
{
|
||||
if (!initSocket())
|
||||
{
|
||||
{//初始化失败
|
||||
return false;
|
||||
}
|
||||
struct addrinfo* answer, hint;
|
||||
@ -47,27 +51,25 @@ bool SocketC::Connect(string IP, UINT Prot)
|
||||
ZeroMemory(&hint, sizeof(hint));
|
||||
hint.ai_family = AF_INET;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
|
||||
SOCKADDR_IN server_addr;
|
||||
|
||||
//解析域名(如果传入的IP是域名的情况)
|
||||
if (getaddrinfo(IP.c_str(), NULL, &hint, &answer) == 0)
|
||||
{
|
||||
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_port = htons(Prot);
|
||||
((SOCKADDR_IN*)&hint.ai_addr)->sin_port = htons(Prot);
|
||||
|
||||
|
||||
//´´½¨Ì×½Ó×Ö
|
||||
sclient = socket(AF_INET, SOCK_STREAM, 0);
|
||||
//连接到服务器
|
||||
if (connect(sclient, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR)
|
||||
{
|
||||
{//连接失败
|
||||
WSACleanup();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
{//连接成功创建线程接收数据
|
||||
state = 1;
|
||||
rec = std::thread((&SocketC::Receive), this);
|
||||
return true;
|
||||
@ -76,66 +78,85 @@ bool SocketC::Connect(string IP, UINT Prot)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//接收数据函数
|
||||
VOID SocketC::Receive()
|
||||
{
|
||||
char* buff = NULL;
|
||||
while(state)
|
||||
{
|
||||
//开始接收数据
|
||||
char buf[1024] = { 0 };
|
||||
int len = recv(sclient, buf, 1024, 0);
|
||||
int len = recv(sclient, buf, 1020, 0);
|
||||
if (len ==SOCKET_ERROR || len == 0)
|
||||
{
|
||||
{//服务器关闭了
|
||||
state = 0;
|
||||
if (Cfunc != NULL)
|
||||
{
|
||||
Cfunc();
|
||||
}
|
||||
cout << "·þÎñÆ÷¶Ï¿ªÁ¬½Ó";
|
||||
//cout << "服务器断开连接";
|
||||
break;
|
||||
}
|
||||
int isStr;
|
||||
buff = RecvBuff(buf, len, isStr);
|
||||
while (buff)
|
||||
{
|
||||
if (m_mode == 0)
|
||||
{//普通模式直接处理
|
||||
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;
|
||||
string str = aes.DecryptionAES(buff, "qwertyuiopasdfgh");
|
||||
Rfunc((char*)str.c_str(), str.length());
|
||||
if (isStr == 1)
|
||||
{//如果是字符串先解密
|
||||
AES aes;
|
||||
string str = aes.DecryptionAES(buff, "qwertyuiopasdfgh");
|
||||
Rfunc((char*)str.c_str(), str.length());
|
||||
}
|
||||
else
|
||||
Rfunc(buff, len);
|
||||
}
|
||||
else
|
||||
Rfunc(buff, len);
|
||||
delete buff;
|
||||
len = 0;
|
||||
buff = RecvBuff(NULL, len, isStr);
|
||||
}
|
||||
delete buff;
|
||||
len = 0;
|
||||
buff = RecvBuff(NULL, len, isStr);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//处理收到的数据
|
||||
char* SocketC::RecvBuff(char* buf, int& len, int& isStr)
|
||||
{
|
||||
char* buff = NULL;
|
||||
MsgHead* h;
|
||||
lock_guard<std::mutex> guard(msgLock);
|
||||
//lock_guard<std::mutex> guard(msgLock);
|
||||
//把收到的数据复制到缓冲区
|
||||
if (len != 0)
|
||||
memcpy_s(tmpBuf + bufLen, len, buf, len);
|
||||
bufLen += len;
|
||||
|
||||
//判断缓冲区内的消息长度是否大于消息头
|
||||
if (bufLen > sizeof(MsgHead))
|
||||
{
|
||||
{//检查消息头是由有问题
|
||||
h = (MsgHead*)tmpBuf;
|
||||
if (!CheckHead(h))
|
||||
{//消息头不合规关闭连接
|
||||
closesocket(sclient);
|
||||
return NULL;
|
||||
}
|
||||
//判断当前消息是否收完
|
||||
if (bufLen - sizeof(MsgHead) >= h->bufLen)
|
||||
{
|
||||
{//当前消息收完了
|
||||
buff = new char[h->bufLen + 1];
|
||||
ZeroMemory(buff, h->bufLen + 1);
|
||||
memcpy_s(buff, h->bufLen, tmpBuf + sizeof(MsgHead), h->bufLen);
|
||||
len = h->bufLen;
|
||||
isStr = h->isStr;
|
||||
bufLen = bufLen - len - sizeof(MsgHead);
|
||||
//缓冲区数据前移
|
||||
if (bufLen > 0)
|
||||
memcpy_s(tmpBuf, bufLen, tmpBuf + sizeof(MsgHead) + len, bufLen);
|
||||
}
|
||||
@ -143,53 +164,104 @@ char* SocketC::RecvBuff(char* buf, int& len, int& isStr)
|
||||
return buff;
|
||||
}
|
||||
|
||||
|
||||
int SocketC::SendData(const char* Date, int len, int isStr)
|
||||
//检查消息头
|
||||
BOOL SocketC::CheckHead(MsgHead* h)
|
||||
{
|
||||
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, Date, len);
|
||||
int lenth = send(sclient, buff, len + sizeof(MsgHead), 0) - sizeof(MsgHead);
|
||||
delete[] buff;
|
||||
if (lenth < 0)
|
||||
//消息长度不能大于10000
|
||||
if (h->bufLen > 10000)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (str == "")
|
||||
return FALSE;
|
||||
AES aes;
|
||||
string sendStr = aes.EncryptionAES(str, "qwertyuiopasdfgh");
|
||||
if (-1 == SendData(sendStr.c_str(), sendStr.length(), 1))
|
||||
{
|
||||
return FALSE;
|
||||
if (m_mode == 0)
|
||||
{//普通模式直接发送
|
||||
if (send(sclient, str.c_str(), str.length(), 0) == -1)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
//设置接收数据的回调函数
|
||||
VOID SocketC::SetRecvFunc(function<VOID(char*, int)> fun)
|
||||
{
|
||||
Rfunc = fun;
|
||||
}
|
||||
|
||||
//设置断开连接的回调函数
|
||||
VOID SocketC::SetCloseFunc(function<VOID()> fun)
|
||||
{
|
||||
Cfunc = fun;
|
||||
}
|
||||
|
||||
//断开连接
|
||||
void SocketC::Close()
|
||||
{
|
||||
if (state != 0)
|
||||
|
@ -23,26 +23,26 @@ private:
|
||||
char token[34] = { 0 };
|
||||
};
|
||||
|
||||
char tmpBuf[10240] = { 0 };
|
||||
int bufLen = 0;
|
||||
SOCKET sclient = 0;
|
||||
BOOL state = 0;
|
||||
std::thread rec;
|
||||
std::mutex msgLock;
|
||||
function<VOID(char*, int)> Rfunc = NULL;
|
||||
function<VOID()> Cfunc = NULL;
|
||||
bool initSocket();
|
||||
VOID Receive();
|
||||
char* RecvBuff(char* buf, int& len, int& isStr);
|
||||
|
||||
char tmpBuf[10240] = { 0 }; //缓冲区
|
||||
int bufLen = 0; //当前接收了多长的数据
|
||||
SOCKET sclient = 0; //socket客户端
|
||||
BOOL state = 0; //当前状态
|
||||
int m_mode; //当前工作的模式
|
||||
std::thread rec; //用来接数据的收线程
|
||||
function<VOID(char*, int)> Rfunc = NULL; //接收到了数据的回调函数
|
||||
function<VOID()> Cfunc = NULL; //断开连接的回调函数
|
||||
bool initSocket(); //初始化socket
|
||||
VOID Receive(); //接收数据函数
|
||||
char* RecvBuff(char* buf, int& len, int& isStr); //处理收到的数据
|
||||
BOOL CheckHead(MsgHead* h); //检查消息头
|
||||
|
||||
public:
|
||||
SocketC(int bufSize = 4096, int modo = 0);
|
||||
~SocketC();
|
||||
bool Connect(string IP, UINT Prot);
|
||||
int SendData(const char* Date, int len, int isStr = 0);
|
||||
BOOL SendStr(string str);
|
||||
VOID SetRecvFunc(function<VOID(char*, int)> fun);
|
||||
VOID SetCloseFunc(function<VOID()> fun);
|
||||
void Close();
|
||||
SocketC(int mode = 0); //构造
|
||||
~SocketC(); //析构
|
||||
bool Connect(string IP, UINT Prot); //连接到服务器
|
||||
int SendData(const char* Date, int len, int isStr = 0); //发送数据包
|
||||
BOOL SendStr(string str); //发送字符串
|
||||
VOID SetRecvFunc(function<VOID(char*, int)> fun); //设置接收数据的回调函数
|
||||
VOID SetCloseFunc(function<VOID()> fun); //设置断开连接的回调函数
|
||||
void Close(); //断开连接
|
||||
};
|
||||
|
@ -6,7 +6,7 @@ using namespace std;
|
||||
|
||||
|
||||
|
||||
SocketC c;
|
||||
SocketC c(1);
|
||||
int flag = 1;
|
||||
int myName = 0;
|
||||
|
||||
|
@ -15,33 +15,45 @@ DWORD WINAPI SocketS::ThreadProc(LPVOID lpParameter)
|
||||
while (server->g_flag)
|
||||
{//获取完成端口的数据
|
||||
BOOL bFlag = GetQueuedCompletionStatus(port, &len, &index, &lpOverlapped, INFINITE);
|
||||
server->Lock.lock();
|
||||
//server->Lock.lock();
|
||||
clienInfo* clien = &server->ClienMap[index];
|
||||
if (bFlag == TRUE && len > 0)
|
||||
{// 接收到客户端消息
|
||||
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
|
||||
if (server->m_mode == 0)
|
||||
{//普通模式
|
||||
if (server->Rfunc != NULL)
|
||||
{
|
||||
server->Rfunc(index, clien->buff, len);
|
||||
}
|
||||
ZeroMemory(clien->buff, sizeof(clien->buff));
|
||||
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
|
||||
{//客户端关闭
|
||||
@ -52,15 +64,22 @@ DWORD WINAPI SocketS::ThreadProc(LPVOID lpParameter)
|
||||
server->CloseClien(index);
|
||||
}
|
||||
|
||||
server->Lock.unlock();
|
||||
//server->Lock.unlock();
|
||||
}
|
||||
server->Count--;
|
||||
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;
|
||||
clienInfo* clien = &ClienMap[index];
|
||||
if (clien->Rbuflen < sizeof(MsgHead))
|
||||
{//收到的消息还没消息头长
|
||||
wsabuf.buf = (char*)&clien->h + clien->Rbuflen;
|
||||
wsabuf.len = sizeof(MsgHead) - clien->Rbuflen;
|
||||
}
|
||||
else
|
||||
if (m_mode == 0)
|
||||
{
|
||||
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);
|
||||
wsabuf.buf = clien->buff;
|
||||
wsabuf.len = 1020;
|
||||
}
|
||||
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 dwFlag = 0;
|
||||
@ -217,6 +245,8 @@ BOOL SocketS::Creat(int Prot)
|
||||
//关闭服务端
|
||||
void SocketS::Close()
|
||||
{//清除客户端
|
||||
if (g_flag == 0)
|
||||
return;
|
||||
g_flag = 0;
|
||||
Lock.lock();
|
||||
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)
|
||||
{//创建消息头生成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;
|
||||
{
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
if (m_mode == 0)
|
||||
{//普通模式
|
||||
return PostSend(index, buf, len);
|
||||
}
|
||||
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 == "")
|
||||
return FALSE;
|
||||
//加密字符串
|
||||
AES aes;
|
||||
string sendStr = aes.EncryptionAES(str,"qwertyuiopasdfgh");
|
||||
//发送消息
|
||||
if (-1 == SendData(index, sendStr.c_str(), sendStr.length(), 1))
|
||||
{//消息发送失败
|
||||
return FALSE;
|
||||
if (m_mode == 0)
|
||||
{//普通模式
|
||||
if (PostSend(index, str.c_str(), str.length()) == -1)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ private:
|
||||
std::thread *ListenClien; //监听线程
|
||||
int Count = 0; //工作者线程多少个
|
||||
mutex Lock; //线程锁
|
||||
int m_mode; //当前工作的模式
|
||||
function<VOID(int,char*,int)> Rfunc = NULL; //接收数据的回调函数
|
||||
function<VOID(int)> Cfunc = NULL; //客户端关闭的回调函数
|
||||
|
||||
@ -55,7 +56,8 @@ private:
|
||||
VOID Listens(); //监听消息函数
|
||||
|
||||
public:
|
||||
SocketS(); //¹¹Ôì
|
||||
SocketS(int mode = 0); //构造
|
||||
~SocketS(); //构造
|
||||
BOOL Creat(int Prot); //创建服务端
|
||||
void Close(); //关闭服务端
|
||||
VOID SetRecvFunc(function<VOID(int, char*, int)> fun); //设置接收消息的回调函数
|
||||
|
@ -29,7 +29,7 @@ struct msgInfo
|
||||
std::map<int/*name*/, int/*index*/> clienMap;
|
||||
std::map<int/*index*/, int/*name*/> clienIndex;
|
||||
|
||||
SocketS s;
|
||||
SocketS s(1);
|
||||
int cont = 0;
|
||||
VOID closeFunc(int index)
|
||||
{
|
||||
@ -52,8 +52,8 @@ VOID recvFunc(int index, char* buf, int len)
|
||||
int main(void)
|
||||
{
|
||||
//s.SetRecvFunc([&tt](SocketS::msgInfo info) {return tt.ppp(info); });
|
||||
s.Creat(6666);
|
||||
s.Close();
|
||||
//s.Creat(6666);
|
||||
//s.Close();
|
||||
|
||||
s.SetCloseFunc(closeFunc);
|
||||
s.SetRecvFunc(recvFunc);
|
||||
|
176
网页请求/SocketC.cpp
176
网页请求/SocketC.cpp
@ -1,5 +1,6 @@
|
||||
#include "SocketC.h"
|
||||
|
||||
//初始化socket
|
||||
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()
|
||||
{
|
||||
if (state == 1)
|
||||
@ -36,10 +39,11 @@ SocketC::~SocketC()
|
||||
}
|
||||
}
|
||||
|
||||
//连接到服务器
|
||||
bool SocketC::Connect(string IP, UINT Prot)
|
||||
{
|
||||
if (!initSocket())
|
||||
{
|
||||
{//初始化失败
|
||||
return false;
|
||||
}
|
||||
struct addrinfo* answer, hint;
|
||||
@ -47,27 +51,25 @@ bool SocketC::Connect(string IP, UINT Prot)
|
||||
ZeroMemory(&hint, sizeof(hint));
|
||||
hint.ai_family = AF_INET;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
|
||||
SOCKADDR_IN server_addr;
|
||||
|
||||
//解析域名(如果传入的IP是域名的情况)
|
||||
if (getaddrinfo(IP.c_str(), NULL, &hint, &answer) == 0)
|
||||
{
|
||||
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_port = htons(Prot);
|
||||
((SOCKADDR_IN*)&hint.ai_addr)->sin_port = htons(Prot);
|
||||
|
||||
|
||||
//创建套接字
|
||||
sclient = socket(AF_INET, SOCK_STREAM, 0);
|
||||
//连接到服务器
|
||||
if (connect(sclient, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR)
|
||||
{
|
||||
{//连接失败
|
||||
WSACleanup();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
{//连接成功创建线程接收数据
|
||||
state = 1;
|
||||
rec = std::thread((&SocketC::Receive), this);
|
||||
return true;
|
||||
@ -76,15 +78,17 @@ bool SocketC::Connect(string IP, UINT Prot)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//接收数据函数
|
||||
VOID SocketC::Receive()
|
||||
{
|
||||
char* buff = NULL;
|
||||
while(state)
|
||||
{
|
||||
//开始接收数据
|
||||
char buf[1024] = { 0 };
|
||||
int len = recv(sclient, buf, 1024, 0);
|
||||
int len = recv(sclient, buf, 1020, 0);
|
||||
if (len ==SOCKET_ERROR || len == 0)
|
||||
{
|
||||
{//服务器关闭了
|
||||
state = 0;
|
||||
if (Cfunc != NULL)
|
||||
{
|
||||
@ -93,49 +97,66 @@ VOID SocketC::Receive()
|
||||
//cout << "服务器断开连接";
|
||||
break;
|
||||
}
|
||||
int isStr;
|
||||
buff = RecvBuff(buf, len, isStr);
|
||||
while (buff)
|
||||
{
|
||||
if (m_mode == 0)
|
||||
{//普通模式直接处理
|
||||
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;
|
||||
string str = aes.DecryptionAES(buff, "qwertyuiopasdfgh");
|
||||
Rfunc((char*)str.c_str(), str.length());
|
||||
if (isStr == 1)
|
||||
{//如果是字符串先解密
|
||||
AES aes;
|
||||
string str = aes.DecryptionAES(buff, "qwertyuiopasdfgh");
|
||||
Rfunc((char*)str.c_str(), str.length());
|
||||
}
|
||||
else
|
||||
Rfunc(buff, len);
|
||||
}
|
||||
else
|
||||
Rfunc(buff, len);
|
||||
delete buff;
|
||||
len = 0;
|
||||
buff = RecvBuff(NULL, len, isStr);
|
||||
}
|
||||
delete buff;
|
||||
len = 0;
|
||||
buff = RecvBuff(NULL, len, isStr);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//处理收到的数据
|
||||
char* SocketC::RecvBuff(char* buf, int& len, int& isStr)
|
||||
{
|
||||
char* buff = NULL;
|
||||
MsgHead* h;
|
||||
lock_guard<std::mutex> guard(msgLock);
|
||||
//lock_guard<std::mutex> guard(msgLock);
|
||||
//把收到的数据复制到缓冲区
|
||||
if (len != 0)
|
||||
memcpy_s(tmpBuf + bufLen, len, buf, len);
|
||||
bufLen += len;
|
||||
|
||||
//判断缓冲区内的消息长度是否大于消息头
|
||||
if (bufLen > sizeof(MsgHead))
|
||||
{
|
||||
{//检查消息头是由有问题
|
||||
h = (MsgHead*)tmpBuf;
|
||||
if (!CheckHead(h))
|
||||
{//消息头不合规关闭连接
|
||||
closesocket(sclient);
|
||||
return NULL;
|
||||
}
|
||||
//判断当前消息是否收完
|
||||
if (bufLen - sizeof(MsgHead) >= h->bufLen)
|
||||
{
|
||||
{//当前消息收完了
|
||||
buff = new char[h->bufLen + 1];
|
||||
ZeroMemory(buff, h->bufLen + 1);
|
||||
memcpy_s(buff, h->bufLen, tmpBuf + sizeof(MsgHead), h->bufLen);
|
||||
len = h->bufLen;
|
||||
isStr = h->isStr;
|
||||
bufLen = bufLen - len - sizeof(MsgHead);
|
||||
//缓冲区数据前移
|
||||
if (bufLen > 0)
|
||||
memcpy_s(tmpBuf, bufLen, tmpBuf + sizeof(MsgHead) + len, bufLen);
|
||||
}
|
||||
@ -143,53 +164,104 @@ char* SocketC::RecvBuff(char* buf, int& len, int& isStr)
|
||||
return buff;
|
||||
}
|
||||
|
||||
|
||||
int SocketC::SendData(const char* Date, int len, int isStr)
|
||||
//检查消息头
|
||||
BOOL SocketC::CheckHead(MsgHead* h)
|
||||
{
|
||||
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, Date, len);
|
||||
int lenth = send(sclient, buff, len + sizeof(MsgHead), 0) - sizeof(MsgHead);
|
||||
delete[] buff;
|
||||
if (lenth < 0)
|
||||
//消息长度不能大于10000
|
||||
if (h->bufLen > 10000)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (str == "")
|
||||
return FALSE;
|
||||
AES aes;
|
||||
string sendStr = aes.EncryptionAES(str, "qwertyuiopasdfgh");
|
||||
if (-1 == SendData(sendStr.c_str(), sendStr.length(), 1))
|
||||
{
|
||||
return FALSE;
|
||||
if (m_mode == 0)
|
||||
{//普通模式直接发送
|
||||
if (send(sclient, str.c_str(), str.length(), 0) == -1)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
//设置接收数据的回调函数
|
||||
VOID SocketC::SetRecvFunc(function<VOID(char*, int)> fun)
|
||||
{
|
||||
Rfunc = fun;
|
||||
}
|
||||
|
||||
//设置断开连接的回调函数
|
||||
VOID SocketC::SetCloseFunc(function<VOID()> fun)
|
||||
{
|
||||
Cfunc = fun;
|
||||
}
|
||||
|
||||
//断开连接
|
||||
void SocketC::Close()
|
||||
{
|
||||
if (state != 0)
|
||||
|
@ -1,8 +1,16 @@
|
||||
#pragma once
|
||||
#include "pub.h"
|
||||
#include<iostream>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <functional>
|
||||
#include "md5.h"
|
||||
#include "AES.h"
|
||||
|
||||
#pragma comment(lib,"ws2_32.lib")
|
||||
using namespace std;
|
||||
|
||||
class SocketC
|
||||
{
|
||||
private:
|
||||
@ -15,26 +23,26 @@ private:
|
||||
char token[34] = { 0 };
|
||||
};
|
||||
|
||||
char tmpBuf[10240] = { 0 };
|
||||
int bufLen = 0;
|
||||
SOCKET sclient = 0;
|
||||
BOOL state = 0;
|
||||
std::thread rec;
|
||||
std::mutex msgLock;
|
||||
function<VOID(char*, int)> Rfunc = NULL;
|
||||
function<VOID()> Cfunc = NULL;
|
||||
bool initSocket();
|
||||
VOID Receive();
|
||||
char* RecvBuff(char* buf, int& len, int& isStr);
|
||||
|
||||
char tmpBuf[10240] = { 0 }; //缓冲区
|
||||
int bufLen = 0; //当前接收了多长的数据
|
||||
SOCKET sclient = 0; //socket客户端
|
||||
BOOL state = 0; //当前状态
|
||||
int m_mode; //当前工作的模式
|
||||
std::thread rec; //用来接数据的收线程
|
||||
function<VOID(char*, int)> Rfunc = NULL; //接收到了数据的回调函数
|
||||
function<VOID()> Cfunc = NULL; //断开连接的回调函数
|
||||
bool initSocket(); //初始化socket
|
||||
VOID Receive(); //接收数据函数
|
||||
char* RecvBuff(char* buf, int& len, int& isStr); //处理收到的数据
|
||||
BOOL CheckHead(MsgHead* h); //检查消息头
|
||||
|
||||
public:
|
||||
SocketC(int bufSize = 4096, int modo = 0);
|
||||
~SocketC();
|
||||
bool Connect(string IP, UINT Prot);
|
||||
int SendData(const char* Date, int len, int isStr = 0);
|
||||
BOOL SendStr(string str);
|
||||
VOID SetRecvFunc(function<VOID(char*, int)> fun);
|
||||
VOID SetCloseFunc(function<VOID()> fun);
|
||||
void Close();
|
||||
SocketC(int mode = 0); //构造
|
||||
~SocketC(); //析构
|
||||
bool Connect(string IP, UINT Prot); //连接到服务器
|
||||
int SendData(const char* Date, int len, int isStr = 0); //发送数据包
|
||||
BOOL SendStr(string str); //发送字符串
|
||||
VOID SetRecvFunc(function<VOID(char*, int)> fun); //设置接收数据的回调函数
|
||||
VOID SetCloseFunc(function<VOID()> fun); //设置断开连接的回调函数
|
||||
void Close(); //断开连接
|
||||
};
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "Json.h"
|
||||
#include "SocketC.h"
|
||||
|
||||
SocketC tcpc;
|
||||
SocketC tcpc(1);
|
||||
|
||||
char* U8ToUnicode(char* szU8)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user