优化网络服务端和客户端

This commit is contained in:
~ Alone 2024-10-23 23:58:57 +08:00
parent 9e6c36bd4b
commit f53586dad5
6 changed files with 322 additions and 286 deletions

View File

@ -73,46 +73,101 @@ bool SocketC::Connect(string IP, UINT Prot)
VOID SocketC::Receive() VOID SocketC::Receive()
{ {
char* buff = NULL;
while(state) while(state)
{ {
MsgInfo* info = new MsgInfo; char buf[2048] = { 0 };
info->len = recv(sclient, info->buff, 2047, 0); int len = recv(sclient, buf, 2048, 0);
msgLock.lock(); if (len ==SOCKET_ERROR || len == 0)
msgList.push_back(info); {
msgLock.unlock(); state = 0;
if (Cfunc != NULL)
{
Cfunc();
}
cout << "服务器断开连接";
break;
}
buff = RecvBuff(buf, len);
while (buff)
{
if (Rfunc != NULL)
{
Rfunc(buff, len);
}
delete buff;
len = 0;
buff = RecvBuff(NULL, len);
}
} }
return; return;
} }
int SocketC::Send(const char* Date, int len) char* SocketC::RecvBuff(char* buf, int& len)
{ {
return send(sclient, Date, len, 0); char* buff = NULL;
MsgHead* h;
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 (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;
bufLen = bufLen - len - sizeof(MsgHead);
if (bufLen > 0)
memcpy_s(tmpBuf, bufLen, tmpBuf + sizeof(MsgHead) + len, bufLen);
}
}
return buff;
} }
SocketC::MsgInfo* SocketC::GetMsg()
int SocketC::Send(const char* Date, int len)
{ {
MsgInfo* info = NULL; MsgHead h;
msgLock.lock(); h.bufLen = len;
if (msgList.size() > 0) time(&h.tm);
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)
{ {
info = *msgList.begin(); lenth = -1;
msgList.pop_front();
} }
msgLock.unlock(); return lenth;
return info; }
VOID SocketC::SetRecvFunc(function<VOID(char*, int)> fun)
{
Rfunc = fun;
}
VOID SocketC::SetCloseFunc(function<VOID()> fun)
{
Cfunc = fun;
} }
void SocketC::Close() void SocketC::Close()
{ {
state = 0; if (state != 0)
//¹Ø±ÕÌ×½Ó×Ö {
closesocket(sclient); state = 0;
//ÊÍ·ÅDLL×ÊÔ´ //关闭套接字
shutdown(sclient, SD_BOTH);
closesocket(sclient);
//释放DLL资源
rec.join();
}
WSACleanup(); WSACleanup();
//for (size_t i = 0; i < msgList.size(); i++)
//{
//
//}
msgList.clear();
rec.join();
} }

View File

@ -3,9 +3,8 @@
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <thread> #include <thread>
#include <map>
#include <mutex> #include <mutex>
#include <list> #include <functional>
#pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib")
@ -13,24 +12,34 @@ using namespace std;
class SocketC class SocketC
{ {
public:
struct MsgInfo
{
int len = 0; //ÄÚÈݳ¤¶È
char buff[2048] = {0}; //ÏûÏ¢ÄÚÈÝ
};
private: private:
struct MsgHead
{
int MyIndex = 0;
int bufLen = 0;
time_t tm = 0;
char token[34] = { 0 };
};
char tmpBuf[10240] = { 0 };
int bufLen = 0;
SOCKET sclient = 0; SOCKET sclient = 0;
std::list<MsgInfo*>msgList;
BOOL state = 0; BOOL state = 0;
std::thread rec; std::thread rec;
std::mutex msgLock; std::mutex msgLock;
function<VOID(char*, int)> Rfunc = NULL;
function<VOID()> Cfunc = NULL;
bool initSocket(); bool initSocket();
VOID Receive(); VOID Receive();
char* RecvBuff(char* buf, int& len);
public: public:
~SocketC(); ~SocketC();
bool Connect(string IP, UINT Prot); bool Connect(string IP, UINT Prot);
int Send(const char* Date, int len); int Send(const char* Date, int len);
MsgInfo* GetMsg();
VOID SetRecvFunc(function<VOID(char*, int)> fun);
VOID SetCloseFunc(function<VOID()> fun);
void Close(); void Close();
}; };

View File

@ -1,135 +1,42 @@
#include<iostream> #include<iostream>
#include "SocketC.h" #include "SocketC.h"
#include <string>
using namespace std; using namespace std;
struct clienMsg
{
int myName;
int snedName;
int code;
int len;
char buf[1024];
};
SocketC c; SocketC c;
int flag = 1; int flag = 1;
int myName = 0; int myName = 0;
VOID LogIn() { void recvFunc(char* buf, int len)
if (myName != 0)
{
cout << "当前已登录无需重复登录,当前账号:"<<myName<<"\n";
return;
}
int name;
char pass[16] = { 0 };
cout << "请输入账号:";
cin >> name;
cout << "请输入密码:";
cin >> pass;
clienMsg msg;
msg.myName = name;
msg.code = 1;
msg.snedName = 0;
memcpy_s(msg.buf, 16, pass, 16);
c.Send((char*)&msg, sizeof(clienMsg));
}
VOID SendMsg()
{ {
if (myName == 0) cout << buf << "\n";
{ }
cout << "请先登录账号\n"; void closeFunc()
return; {
} cout << "服务器断开连接";
int name;
char buf[1000] = { 0 };
cout << "你要给那个账号发消息\n";
cin >> name;
cout << "请输入要发送的内容:";
cin >> buf;
clienMsg msg;
msg.myName = myName;
msg.snedName = name;
msg.code = 2;
memcpy_s(msg.buf, 1000, buf, 1000);
c.Send((char*)&msg, sizeof(clienMsg));
} }
int main() { int main() {
c.SetRecvFunc(recvFunc);
c.SetCloseFunc(closeFunc);
c.Connect("127.0.0.1", 6666); c.Connect("127.0.0.1", 6666);
string str;
thread th([] { for (int i = 0; i < 10000000; i++)
while (flag)
{
SocketC::MsgInfo* info;
clienMsg* msg;
info = c.GetMsg();
if (info)
{
msg = (clienMsg*)info->buff;
std::string buf;
buf = msg->buf;
switch (msg->code)
{
case 1:
cout << buf << "\n";
if (buf == "登录成功")
{
myName = msg->myName;
}
else
{
myName = 0;
}
break;
case 2:
if (msg->len != -1)
cout << msg->myName << "对你说:";
cout << buf << "\n";
break;
default:
break;
}
delete info;
}
else
{
Sleep(10);
}
}
});
cout << "输入1登录账号\n";
cout << "输入2给他人发消息\n";
cout << "输入其他退出系统\n";
int code = 0;
while (1)
{ {
cin >> code; str = to_string(i);
switch (code) c.Send(str.c_str(), str.length());
if (i % 100 == 0)
{ {
case 1: Sleep(100);
LogIn();
break;
case 2:
SendMsg();
break;
default:
flag = 0;
th.join();
c.Close();
return 0;
} }
} }
Sleep(10);
c.Close();
while (1)
{
Sleep(1000);
}
} }

View File

@ -13,23 +13,26 @@ DWORD WINAPI SocketS::ThreadProc(LPVOID lpParameter)
while (server->g_flag) while (server->g_flag)
{ {
BOOL bFlag = GetQueuedCompletionStatus(port, &NumberOfBytes, &index, &lpOverlapped, INFINITE); BOOL bFlag = GetQueuedCompletionStatus(port, &NumberOfBytes, &index, &lpOverlapped, INFINITE);
clienInfo* clien = &server->ClienMap[index];
if (FALSE == bFlag) if (FALSE == bFlag)
{ {
if (64 == GetLastError()) if (64 == GetLastError())
{ {
printf("客户端异常下线\n"); printf("客户端异常下线\n");
msgInfo* info = new msgInfo; clien->c_Sock = 0;
info->index = index; clien->c_Olp.hEvent = NULL;
info->len = -1; server->ClienMap.erase(index);
server->msgLock.lock(); if (server->Cfunc != NULL)
server->msgList.push_back(info); {
server->msgLock.unlock(); server->Cfunc(index);
}
} }
continue; continue;
} }
// 分类处理 // 分类处理
//lock_guard<std::mutex> guard(clien->msgLock);
if (0 == index) // accept if (0 == index) // accept
{ {
printf("accept\n"); printf("accept\n");
@ -39,6 +42,7 @@ DWORD WINAPI SocketS::ThreadProc(LPVOID lpParameter)
{ {
printf("CreateIoCompletionPort 绑定失败 error:%d\n", GetLastError()); printf("CreateIoCompletionPort 绑定失败 error:%d\n", GetLastError());
closesocket(server->ClienMap[server->g_count].c_Sock); closesocket(server->ClienMap[server->g_count].c_Sock);
continue; continue;
} }
server->PostRecv(server->g_count); // 投递recv server->PostRecv(server->g_count); // 投递recv
@ -51,39 +55,41 @@ DWORD WINAPI SocketS::ThreadProc(LPVOID lpParameter)
{ {
printf("客户端正常下线\n"); printf("客户端正常下线\n");
closesocket(server->ClienMap[index].c_Sock); closesocket(clien->c_Sock);
WSACloseEvent(server->ClienMap[index].c_Olp.hEvent); WSACloseEvent(clien->c_Olp.hEvent);
// 从数组中删掉 // 从数组中删掉
server->ClienMap[index].c_Sock = 0; clien->c_Sock = 0;
server->ClienMap[index].c_Olp.hEvent = NULL; clien->c_Olp.hEvent = NULL;
server->ClienMap.erase(index); server->ClienMap.erase(index);
if (server->Cfunc != NULL)
msgInfo* info = new msgInfo; {
info->index = index; server->Cfunc(index);
info->len = -1; }
server->msgLock.lock();
server->msgList.push_back(info);
server->msgLock.unlock();
} }
else else
{ {
if (0 != server->ClienMap[index].c_strRecv) // recv if (0 != clien->c_strRecv) // recv
{ {
// 接收到客户端消息 // 接收到客户端消息
msgInfo* info = new msgInfo; int len = NumberOfBytes;
info->index = index; char * buf = server->RecvBuff(index, clien->c_strRecv, len);
info->len = NumberOfBytes;
memcpy_s(info->buf, NumberOfBytes, server->ClienMap[index].c_strRecv, NumberOfBytes);
server->msgLock.lock(); while (buf)
server->msgList.push_back(info); {
server->msgLock.unlock(); if (server->Rfunc != NULL)
{
memset(server->ClienMap[index].c_strRecv, 0, sizeof(server->ClienMap[index].c_strRecv)); server->Rfunc(index, buf, len);
}
delete buf;
len = 0;
buf = server->RecvBuff(index,NULL, len);
}
memset(clien->c_strRecv, 0, sizeof(clien->c_strRecv));
server->PostRecv(index); // 对自己投递接收 server->PostRecv(index); // 对自己投递接收
} }
} }
} }
} }
return 0; return 0;
@ -130,15 +136,42 @@ int SocketS::PostRecv(int index)
int SocketS::PostSend(int index, const char* buf, int len) int SocketS::PostSend(int index, const char* buf, int len)
{ {
if (ClienMap.find(index) != ClienMap.end()) if (ClienMap.find(index) != ClienMap.end())
{ {
lock_guard<std::mutex> guard(ClienMap[index].sendLock);
if (ClienMap[index].c_Sock != 0) if (ClienMap[index].c_Sock != 0)
{ {
return send(ClienMap[index].c_Sock, buf, len, 0); return send(ClienMap[index].c_Sock, buf, len, 0);
} }
} }
return 0; return -1;
}
char* SocketS::RecvBuff(int index, char* buf, int& len)
{
char* buff = NULL;
MsgHead* h;
clienInfo* info = &ClienMap[index];
lock_guard<std::mutex> guard(info->msgLock);
if (len != 0)
memcpy_s(info->buf + info->buflen, len, buf, len);
info->buflen += len;
if (info->buflen > sizeof(MsgHead))
{
h = (MsgHead*)info->buf;
if (info->buflen - sizeof(MsgHead) >= h->bufLen)
{
buff = new char[h->bufLen + 1];
ZeroMemory(buff, h->bufLen + 1);
memcpy_s(buff, h->bufLen, info->buf + sizeof(MsgHead), h->bufLen);
len = h->bufLen;
info->buflen = info->buflen - len - sizeof(MsgHead);
if (info->buflen > 0)
memcpy_s(info->buf, info->buflen, info->buf + sizeof(MsgHead) + len, info->buflen);
}
}
return buff;
} }
BOOL SocketS::Creat(int Prot) BOOL SocketS::Creat(int Prot)
@ -187,7 +220,7 @@ BOOL SocketS::Creat(int Prot)
sockAddress.sin_family = AF_INET; sockAddress.sin_family = AF_INET;
sockAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // INADDR_ANY --- 任何地址都可以 sockAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // INADDR_ANY --- 任何地址都可以
sockAddress.sin_port = htons(Prot); sockAddress.sin_port = htons(Prot);
if (SOCKET_ERROR == bind(socketServer, (struct sockaddr*)&sockAddress, sizeof(sockAddress))) if (SOCKET_ERROR == ::bind(socketServer, (struct sockaddr*)&sockAddress, sizeof(sockAddress)))
{ {
printf("bind 失败 error:%d\n", WSAGetLastError()); printf("bind 失败 error:%d\n", WSAGetLastError());
closesocket(socketServer); closesocket(socketServer);
@ -232,7 +265,7 @@ BOOL SocketS::Creat(int Prot)
if (0 != PostAccept()) if (0 != PostAccept())
{ {
Clear(); Close();
WSACleanup(); WSACleanup();
return -1; return -1;
} }
@ -259,7 +292,7 @@ BOOL SocketS::Creat(int Prot)
} }
void SocketS::Clear() void SocketS::Close()
{ {
g_flag = FALSE; g_flag = FALSE;
for (auto i = ClienMap.begin(); i != ClienMap.end(); ++i) for (auto i = ClienMap.begin(); i != ClienMap.end(); ++i)
@ -276,17 +309,69 @@ void SocketS::Clear()
free(pThread); free(pThread);
CloseHandle(hPort); CloseHandle(hPort);
WSACleanup(); WSACleanup();
Rfunc = NULL;
Cfunc = NULL;
} }
SocketS::msgInfo* SocketS::GetMsg() VOID SocketS::SetRecvFunc(function<VOID(int, char*, int)> fun)
{ {
msgInfo* info = NULL; Rfunc = fun;
msgLock.lock();
if (msgList.size() > 0)
{
info = *msgList.begin();
msgList.pop_front();
}
msgLock.unlock();
return info;
} }
VOID SocketS::SetCloseFunc(function<VOID(int)> fun)
{
Cfunc = fun;
}
VOID SocketS::GetClienName(int index, string& IP, int& Prot)
{
IP = "";
Prot = 0;
if(ClienMap.find(index)!= ClienMap.end())
{
if(ClienMap[index].c_Sock!=0)
{
struct sockaddr_in peerAddr;
int peerLen = sizeof(peerAddr);
getpeername(ClienMap[index].c_Sock, (struct sockaddr*)&peerAddr, &peerLen);
IP = inet_ntoa(peerAddr.sin_addr);
Prot = ntohs(peerAddr.sin_port);
}
}
}
int SocketS::Send(int index,const char* buf, int len)
{
MsgHead h;
h.bufLen = len;
time(&h.tm);
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)
{
lenth = -1;
}
return lenth;
}
VOID SocketS::CloseClien(int index)
{
if (ClienMap.find(index) != ClienMap.end())
{
ClienMap[index].msgLock.lock();
WSACloseEvent(ClienMap[index].c_Olp.hEvent);
shutdown(ClienMap[index].c_Sock, SD_BOTH);
closesocket(ClienMap[index].c_Sock);
ClienMap[index].msgLock.unlock();
// ´ÓÊý×éÖÐɾµô
ClienMap[index].c_Sock = 0;
ClienMap[index].c_Olp.hEvent = NULL;
ClienMap.erase(index);
}
}

View File

@ -10,45 +10,63 @@
#include <string> #include <string>
#include <list> #include <list>
#include <mutex> #include <mutex>
#include <functional>
#include <string>
#pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "Mswsock.lib") #pragma comment(lib, "Mswsock.lib")
using namespace std;
#pragma warning(disable:4996)
class SocketS class SocketS
{ {
public: public:
struct msgInfo
{
int index;
int len = 0;
char buf[1025] = { 0 };
};
private: private:
struct clienInfo struct clienInfo
{ {
SOCKET c_Sock; SOCKET c_Sock;
OVERLAPPED c_Olp; OVERLAPPED c_Olp;
int buflen = 0;
char buf[10240] = { 0 };
char c_strRecv[1024]; char c_strRecv[1024];
mutex msgLock; //消息锁
mutex sendLock; //消息锁
};
struct MsgHead
{
int MyIndex = 0;
int bufLen = 0;
time_t tm = 0;
char token[34] = { 0 };
}; };
BOOL g_flag = TRUE; //状态 BOOL g_flag = TRUE; //状态
HANDLE hPort = NULL; //完成端口句柄 HANDLE hPort = NULL; //完成端口句柄
HANDLE* pThread = NULL; //线程句柄 HANDLE* pThread = NULL; //线程句柄
int g_count = 0; //当前客户端ID int g_count = 0; //当前客户端ID
std::map<int, clienInfo>ClienMap; //所有客户端 map<int, clienInfo>ClienMap; //所有客户端
function<VOID(int,char*,int)> Rfunc = NULL;
function<VOID(int)> Cfunc = NULL;
std::mutex msgLock; //消息锁
std::list<msgInfo*>msgList; //存放所有消息
static DWORD WINAPI ThreadProc(LPVOID lpParameter); //工作者线程 static DWORD WINAPI ThreadProc(LPVOID lpParameter); //工作者线程
public:
SocketS();
int PostAccept(void); int PostAccept(void);
int PostRecv(int index); int PostRecv(int index);
int PostSend(int index, const char* buf, int len); int PostSend(int index, const char* buf, int len);
char* RecvBuff(int index, char* buf, int& len);
public:
SocketS();
BOOL Creat(int Prot); BOOL Creat(int Prot);
void Clear(); void Close();
msgInfo* GetMsg(); VOID SetRecvFunc(function<VOID(int, char*, int)> fun);
VOID SetCloseFunc(function<VOID(int)> fun);
VOID GetClienName(int index, string& IP, int& Prot);
int Send(int index, const char* buf, int len);
VOID CloseClien(int index);
}; };

View File

@ -1,4 +1,5 @@
#include "SocketS.h" #include "SocketS.h"
//#include "cst.h"
#include <iostream> #include <iostream>
struct clienMsg struct clienMsg
@ -10,94 +11,55 @@ struct clienMsg
char buf[1024]; char buf[1024];
}; };
struct MsgHead
{
int MyIndex = 0;
int SendIndex = 0;
int bufLen = 0;
time_t tm = 0;
//char token[34] = { 0 };
};
struct msgInfo
{
int buflen = 0;
char buf[10240] = { 0 };
};
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;
int cont = 0;
VOID closeFunc(int index)
{
if (clienIndex.find(index) != clienIndex.end())
{
clienMap.erase(clienIndex[index]);
clienIndex.erase(index);
}
}
VOID recvFunc(int index, char* buf, int len)
{
//s.CloseClien(index);
//cout << buf;
string str = buf;
str += "\t";
str += to_string(cont++);
s.Send(index, str.c_str(), str.length());
}
int main(void) int main(void)
{ {
SocketS s; //s.SetRecvFunc([&tt](SocketS::msgInfo info) {return tt.ppp(info); });
s.SetCloseFunc(closeFunc);
s.SetRecvFunc(recvFunc);
s.Creat(6666); s.Creat(6666);
// 阻塞 while(1)
SocketS::msgInfo* info;
clienMsg* msg;
while (1)
{ {
info = s.GetMsg();if (info) Sleep(100);
{
if (info->len == -1)
{
if(clienMap.find(clienIndex[info->index])!= clienMap.end())
{
std::cout << clienIndex[info->index] << "退出登录\n";
clienMap.erase(clienIndex[info->index]);
clienIndex.erase(info->index);
}
delete info;
continue;
}
msg = (clienMsg*)info->buf;
std::string buf;
buf = msg->buf;
switch (msg->code)
{
case 1:
std::cout << msg->myName << "请求登录\n";
if (clienMap.find(msg->myName) == clienMap.end())
{
if (buf == "123456")
{
clienMap[msg->myName] = info->index;
clienIndex[info->index] = msg->myName;
memcpy_s(msg->buf, sizeof("登录成功\0"), "登录成功\0", sizeof("登录成功\0"));
s.PostSend(info->index, (char*)msg, sizeof(clienMsg));
std::cout << msg->myName << "登录成功\n";
}
else
{
memcpy_s(msg->buf, sizeof("密码错误\0"), "密码错误\0", sizeof("密码错误\0"));
s.PostSend(info->index, (char*)msg, sizeof(clienMsg));
std::cout << msg->myName << "登录失败\n";
}
}
else
{
memcpy_s(msg->buf, sizeof("该账号已在其他地方登录\0"), "该账号已在其他地方登录\0", sizeof("该账号已在其他地方登录\0"));
s.PostSend(info->index, (char*)msg, sizeof(clienMsg));
std::cout << msg->myName << "登录失败\n";
}
break;
case 2:
std::cout << msg->myName << "" << msg->snedName << ""<< msg->buf<<"\n";
if (clienMap.find(msg->snedName) == clienMap.end())
{
memcpy_s(msg->buf, sizeof("对方账号不在线\0"), "对方账号不在线\0", sizeof("对方账号不在线\0"));
msg->len = -1;
s.PostSend(info->index, (char*)msg, sizeof(clienMsg));
std::cout << msg->myName << "" << msg->snedName << "消息发送失败\n";
}
else
{
if(s.PostSend(clienMap[msg->snedName], info->buf, info->len)<=0)
{
memcpy_s(msg->buf, sizeof("消息发送失败\0"), "消息发送失败\0", sizeof("消息发送失败\0"));
msg->len = -1;
s.PostSend(info->index, (char*)msg, sizeof(clienMsg));
std::cout << msg->myName << "" << msg->snedName << "消息发送失败\n";
}
}
break;
default:
break;
}
delete info;
}
else
{
Sleep(10);
}
} }
system("pause");
return 0; return 0;
} }