优化网络服务端和客户端

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()
{
char* buff = NULL;
while(state)
{
MsgInfo* info = new MsgInfo;
info->len = recv(sclient, info->buff, 2047, 0);
msgLock.lock();
msgList.push_back(info);
msgLock.unlock();
char buf[2048] = { 0 };
int len = recv(sclient, buf, 2048, 0);
if (len ==SOCKET_ERROR || len == 0)
{
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;
}
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;
msgLock.lock();
if (msgList.size() > 0)
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, Date, len);
int lenth = send(sclient, buff, len + sizeof(MsgHead), 0) - sizeof(MsgHead);
delete[] buff;
if (lenth < 0)
{
info = *msgList.begin();
msgList.pop_front();
lenth = -1;
}
msgLock.unlock();
return info;
return lenth;
}
VOID SocketC::SetRecvFunc(function<VOID(char*, int)> fun)
{
Rfunc = fun;
}
VOID SocketC::SetCloseFunc(function<VOID()> fun)
{
Cfunc = fun;
}
void SocketC::Close()
{
state = 0;
//¹Ø±ÕÌ×½Ó×Ö
closesocket(sclient);
//ÊÍ·ÅDLL×ÊÔ´
if (state != 0)
{
state = 0;
//关闭套接字
shutdown(sclient, SD_BOTH);
closesocket(sclient);
//释放DLL资源
rec.join();
}
WSACleanup();
//for (size_t i = 0; i < msgList.size(); i++)
//{
//
//}
msgList.clear();
rec.join();
}

View File

@ -3,9 +3,8 @@
#include <winsock2.h>
#include <ws2tcpip.h>
#include <thread>
#include <map>
#include <mutex>
#include <list>
#include <functional>
#pragma comment(lib,"ws2_32.lib")
@ -13,24 +12,34 @@ using namespace std;
class SocketC
{
public:
struct MsgInfo
{
int len = 0; //ÄÚÈݳ¤¶È
char buff[2048] = {0}; //ÏûÏ¢ÄÚÈÝ
};
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;
std::list<MsgInfo*>msgList;
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);
public:
~SocketC();
bool Connect(string IP, UINT Prot);
int Send(const char* Date, int len);
MsgInfo* GetMsg();
VOID SetRecvFunc(function<VOID(char*, int)> fun);
VOID SetCloseFunc(function<VOID()> fun);
void Close();
};

View File

@ -1,135 +1,42 @@
#include<iostream>
#include "SocketC.h"
#include <string>
using namespace std;
struct clienMsg
{
int myName;
int snedName;
int code;
int len;
char buf[1024];
};
SocketC c;
int flag = 1;
int myName = 0;
VOID LogIn() {
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()
void recvFunc(char* buf, int len)
{
if (myName == 0)
{
cout << "请先登录账号\n";
return;
}
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));
cout << buf << "\n";
}
void closeFunc()
{
cout << "服务器断开连接";
}
int main() {
c.SetRecvFunc(recvFunc);
c.SetCloseFunc(closeFunc);
c.Connect("127.0.0.1", 6666);
thread th([] {
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)
string str;
for (int i = 0; i < 10000000; i++)
{
cin >> code;
switch (code)
str = to_string(i);
c.Send(str.c_str(), str.length());
if (i % 100 == 0)
{
case 1:
LogIn();
break;
case 2:
SendMsg();
break;
default:
flag = 0;
th.join();
c.Close();
return 0;
Sleep(100);
}
}
Sleep(10);
c.Close();
while (1)
{
Sleep(1000);
}
}

View File

@ -13,23 +13,26 @@ DWORD WINAPI SocketS::ThreadProc(LPVOID lpParameter)
while (server->g_flag)
{
BOOL bFlag = GetQueuedCompletionStatus(port, &NumberOfBytes, &index, &lpOverlapped, INFINITE);
clienInfo* clien = &server->ClienMap[index];
if (FALSE == bFlag)
{
if (64 == GetLastError())
{
printf("客户端异常下线\n");
msgInfo* info = new msgInfo;
info->index = index;
info->len = -1;
server->msgLock.lock();
server->msgList.push_back(info);
server->msgLock.unlock();
clien->c_Sock = 0;
clien->c_Olp.hEvent = NULL;
server->ClienMap.erase(index);
if (server->Cfunc != NULL)
{
server->Cfunc(index);
}
}
continue;
}
// 分类处理
//lock_guard<std::mutex> guard(clien->msgLock);
if (0 == index) // accept
{
printf("accept\n");
@ -39,6 +42,7 @@ DWORD WINAPI SocketS::ThreadProc(LPVOID lpParameter)
{
printf("CreateIoCompletionPort 绑定失败 error:%d\n", GetLastError());
closesocket(server->ClienMap[server->g_count].c_Sock);
continue;
}
server->PostRecv(server->g_count); // 投递recv
@ -51,39 +55,41 @@ DWORD WINAPI SocketS::ThreadProc(LPVOID lpParameter)
{
printf("客户端正常下线\n");
closesocket(server->ClienMap[index].c_Sock);
WSACloseEvent(server->ClienMap[index].c_Olp.hEvent);
closesocket(clien->c_Sock);
WSACloseEvent(clien->c_Olp.hEvent);
// 从数组中删掉
server->ClienMap[index].c_Sock = 0;
server->ClienMap[index].c_Olp.hEvent = NULL;
clien->c_Sock = 0;
clien->c_Olp.hEvent = NULL;
server->ClienMap.erase(index);
msgInfo* info = new msgInfo;
info->index = index;
info->len = -1;
server->msgLock.lock();
server->msgList.push_back(info);
server->msgLock.unlock();
if (server->Cfunc != NULL)
{
server->Cfunc(index);
}
}
else
{
if (0 != server->ClienMap[index].c_strRecv) // recv
if (0 != clien->c_strRecv) // recv
{
// 接收到客户端消息
msgInfo* info = new msgInfo;
info->index = index;
info->len = NumberOfBytes;
memcpy_s(info->buf, NumberOfBytes, server->ClienMap[index].c_strRecv, NumberOfBytes);
int len = NumberOfBytes;
char * buf = server->RecvBuff(index, clien->c_strRecv, len);
server->msgLock.lock();
server->msgList.push_back(info);
server->msgLock.unlock();
memset(server->ClienMap[index].c_strRecv, 0, sizeof(server->ClienMap[index].c_strRecv));
while (buf)
{
if (server->Rfunc != NULL)
{
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); // 对自己投递接收
}
}
}
}
return 0;
@ -130,15 +136,42 @@ int SocketS::PostRecv(int index)
int SocketS::PostSend(int index, const char* buf, int len)
{
if (ClienMap.find(index) != ClienMap.end())
{
lock_guard<std::mutex> guard(ClienMap[index].sendLock);
if (ClienMap[index].c_Sock != 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)
@ -187,7 +220,7 @@ BOOL SocketS::Creat(int Prot)
sockAddress.sin_family = AF_INET;
sockAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // INADDR_ANY --- 任何地址都可以
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());
closesocket(socketServer);
@ -232,7 +265,7 @@ BOOL SocketS::Creat(int Prot)
if (0 != PostAccept())
{
Clear();
Close();
WSACleanup();
return -1;
}
@ -259,7 +292,7 @@ BOOL SocketS::Creat(int Prot)
}
void SocketS::Clear()
void SocketS::Close()
{
g_flag = FALSE;
for (auto i = ClienMap.begin(); i != ClienMap.end(); ++i)
@ -276,17 +309,69 @@ void SocketS::Clear()
free(pThread);
CloseHandle(hPort);
WSACleanup();
Rfunc = NULL;
Cfunc = NULL;
}
SocketS::msgInfo* SocketS::GetMsg()
VOID SocketS::SetRecvFunc(function<VOID(int, char*, int)> fun)
{
msgInfo* info = NULL;
msgLock.lock();
if (msgList.size() > 0)
{
info = *msgList.begin();
msgList.pop_front();
}
msgLock.unlock();
return info;
Rfunc = fun;
}
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 <list>
#include <mutex>
#include <functional>
#include <string>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "Mswsock.lib")
using namespace std;
#pragma warning(disable:4996)
class SocketS
{
public:
struct msgInfo
{
int index;
int len = 0;
char buf[1025] = { 0 };
};
private:
struct clienInfo
{
SOCKET c_Sock;
OVERLAPPED c_Olp;
int buflen = 0;
char buf[10240] = { 0 };
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; //状态
HANDLE hPort = NULL; //完成端口句柄
HANDLE* pThread = NULL; //线程句柄
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); //工作者线程
public:
SocketS();
int PostAccept(void);
int PostRecv(int index);
int PostSend(int index, const char* buf, int len);
char* RecvBuff(int index, char* buf, int& len);
public:
SocketS();
BOOL Creat(int Prot);
void Clear();
msgInfo* GetMsg();
void Close();
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 "cst.h"
#include <iostream>
struct clienMsg
@ -10,94 +11,55 @@ struct clienMsg
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/*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)
{
SocketS s;
//s.SetRecvFunc([&tt](SocketS::msgInfo info) {return tt.ppp(info); });
s.SetCloseFunc(closeFunc);
s.SetRecvFunc(recvFunc);
s.Creat(6666);
// 阻塞
SocketS::msgInfo* info;
clienMsg* msg;
while (1)
while(1)
{
info = s.GetMsg();if (info)
{
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);
}
Sleep(100);
}
system("pause");
return 0;
}