From 06095ace67ceeeb1a53faea3565bccdee5fd31b2 Mon Sep 17 00:00:00 2001 From: hjz <513795900@qq.com> Date: 星期三, 04 十二月 2024 11:52:18 +0800 Subject: [PATCH] Merge branch 'master' of ssh://115.28.86.8:29418/~admin/脸谱AI_0817_1202 --- GroupB_马喜龙/Public/脸谱-设计说明书-B组.docx | 0 GroupB_马喜龙/Public/脸谱-项目计划表-B组.xlsx | 0 GroupB_马喜龙/Server/马喜龙/code/face_painting_socket_server/ServerSocket.h | 70 ++++++++ GroupB_马喜龙/Server/马喜龙/code/face_painting_socket_server/ThreadPool.hpp | 147 ++++++++++++++++++ GroupB_马喜龙/Public/脸谱-风险控制表-B组.docx | 0 GroupB_马喜龙/Server/马喜龙/code/face_painting_socket_server/main.cpp | 39 ++++ GroupB_马喜龙/Public/脸谱-编码规范-B组.docx | 0 GroupB_马喜龙/Public/脸谱-项目需求分析文档-B组.docx | 0 GroupB_马喜龙/Server/马喜龙/code/face_painting_socket_server/ServerSocket.cpp | 187 +++++++++++++++++++++++ GroupB_马喜龙/Server/马喜龙/code/face_painting_socket_server/face_painting_socket_server.sln | 28 +++ 10 files changed, 471 insertions(+), 0 deletions(-) diff --git "a/GroupB_\351\251\254\345\226\234\351\276\231/Public/\350\204\270\350\260\261-\347\274\226\347\240\201\350\247\204\350\214\203-B\347\273\204.docx" "b/GroupB_\351\251\254\345\226\234\351\276\231/Public/\350\204\270\350\260\261-\347\274\226\347\240\201\350\247\204\350\214\203-B\347\273\204.docx" new file mode 100644 index 0000000..674f38b --- /dev/null +++ "b/GroupB_\351\251\254\345\226\234\351\276\231/Public/\350\204\270\350\260\261-\347\274\226\347\240\201\350\247\204\350\214\203-B\347\273\204.docx" Binary files differ diff --git "a/GroupB_\351\251\254\345\226\234\351\276\231/Public/\350\204\270\350\260\261-\350\256\276\350\256\241\350\257\264\346\230\216\344\271\246-B\347\273\204.docx" "b/GroupB_\351\251\254\345\226\234\351\276\231/Public/\350\204\270\350\260\261-\350\256\276\350\256\241\350\257\264\346\230\216\344\271\246-B\347\273\204.docx" new file mode 100644 index 0000000..f3b09a3 --- /dev/null +++ "b/GroupB_\351\251\254\345\226\234\351\276\231/Public/\350\204\270\350\260\261-\350\256\276\350\256\241\350\257\264\346\230\216\344\271\246-B\347\273\204.docx" Binary files differ diff --git "a/GroupB_\351\251\254\345\226\234\351\276\231/Public/\350\204\270\350\260\261-\351\241\271\347\233\256\350\256\241\345\210\222\350\241\250-B\347\273\204.xlsx" "b/GroupB_\351\251\254\345\226\234\351\276\231/Public/\350\204\270\350\260\261-\351\241\271\347\233\256\350\256\241\345\210\222\350\241\250-B\347\273\204.xlsx" new file mode 100644 index 0000000..906aeda --- /dev/null +++ "b/GroupB_\351\251\254\345\226\234\351\276\231/Public/\350\204\270\350\260\261-\351\241\271\347\233\256\350\256\241\345\210\222\350\241\250-B\347\273\204.xlsx" Binary files differ diff --git "a/GroupB_\351\251\254\345\226\234\351\276\231/Public/\350\204\270\350\260\261-\351\241\271\347\233\256\351\234\200\346\261\202\345\210\206\346\236\220\346\226\207\346\241\243-B\347\273\204.docx" "b/GroupB_\351\251\254\345\226\234\351\276\231/Public/\350\204\270\350\260\261-\351\241\271\347\233\256\351\234\200\346\261\202\345\210\206\346\236\220\346\226\207\346\241\243-B\347\273\204.docx" new file mode 100644 index 0000000..40110a3 --- /dev/null +++ "b/GroupB_\351\251\254\345\226\234\351\276\231/Public/\350\204\270\350\260\261-\351\241\271\347\233\256\351\234\200\346\261\202\345\210\206\346\236\220\346\226\207\346\241\243-B\347\273\204.docx" Binary files differ diff --git "a/GroupB_\351\251\254\345\226\234\351\276\231/Public/\350\204\270\350\260\261-\351\243\216\351\231\251\346\216\247\345\210\266\350\241\250-B\347\273\204.docx" "b/GroupB_\351\251\254\345\226\234\351\276\231/Public/\350\204\270\350\260\261-\351\243\216\351\231\251\346\216\247\345\210\266\350\241\250-B\347\273\204.docx" new file mode 100644 index 0000000..5732068 --- /dev/null +++ "b/GroupB_\351\251\254\345\226\234\351\276\231/Public/\350\204\270\350\260\261-\351\243\216\351\231\251\346\216\247\345\210\266\350\241\250-B\347\273\204.docx" Binary files differ diff --git "a/GroupB_\351\251\254\345\226\234\351\276\231/Server/\351\251\254\345\226\234\351\276\231/code/face_painting_socket_server/ServerSocket.cpp" "b/GroupB_\351\251\254\345\226\234\351\276\231/Server/\351\251\254\345\226\234\351\276\231/code/face_painting_socket_server/ServerSocket.cpp" new file mode 100644 index 0000000..46ef42a --- /dev/null +++ "b/GroupB_\351\251\254\345\226\234\351\276\231/Server/\351\251\254\345\226\234\351\276\231/code/face_painting_socket_server/ServerSocket.cpp" @@ -0,0 +1,187 @@ +#include "ServerSocket.h" + +ServerSocket::ServerSocket() +{ + if (initSocket()) cout << "Socket init successed!" << endl; + else cout << "Socket init failed!" << endl; +} + +ServerSocket::~ServerSocket() +{ + closesocket(m_server); + WSACleanup(); +} + +bool ServerSocket::initSocket() +{ + WSAData wsa; + int val = WSAStartup(MAKEWORD(2, 2), &wsa); + if (val != 0) + { + cout << "WSAStartup failed!"<<endl; + } + + m_server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + SOCKADDR_IN addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(PORT); //处理大小端 + addr.sin_addr.S_un.S_addr = 0; + int ret_bind = bind(m_server, (sockaddr*)&addr, sizeof(addr)); + if (ret_bind) { + cout << "bind fail:" << WSAGetLastError() << endl; + return false; + } + int ret_listen = listen(m_server, 5); + if (ret_listen) { + cout << "listen fail:" << WSAGetLastError() << endl; + return false; + } + thread accept_thread(&ServerSocket::acceptThread, this); + accept_thread.detach(); // 防止异常结束 + + thread mMap_Delete(&ServerSocket::mMapDelete, this); + mMap_Delete.detach(); + + return true; +} + +void ServerSocket::acceptThread() +{ + while (true) { + SOCKET client; + SOCKADDR_IN addr; + int len = sizeof(addr); + cout << "waiting for connect..." << endl; + client = accept(m_server, (sockaddr*)&addr, &len); + cout << "client:" << client << endl; + if (client == SOCKET_ERROR) { + cout << "socket 异常" << WSAGetLastError() << endl; + break; + } + else if (client == 0) { + cout << "socket 已关闭:" << WSAGetLastError() << endl; + break; + } + // 正常 连上了 + // 启动长连接线程,进行交互 + mMapInsert(client); + + thread heart_check(&ServerSocket::heartBeatThread, this, client); + heart_check.detach(); + + thread recv_send(&ServerSocket::recvAndSendThread, this, client); + recv_send.detach(); + + } +} + +void ServerSocket::recvAndSendThread(SOCKET client) +{ + while (true) + { + // 解决粘包问题,顺带也解决了拆包问题 + char* buffer = new char[sizeof(Head)]; + int len_recv = recv(client, buffer, sizeof(Head), 0); + int head_rest = sizeof(Head) - len_recv; // 剩余长度 + while (head_rest > 0) { // 保证数据头能够全收到 + len_recv = recv(client, buffer + (sizeof(Head) - head_rest), head_rest, 0); + head_rest -= len_recv; + } + Head* head = (Head*)buffer; // 转成对应结构体,再取出封包总长度 + int len_total = head->len; + //int len_total = *(int*)(buffer + 4); // 还可以直接转为Head*,指出长度 + char* buffer_all = new char[len_total]; + memcpy(buffer_all, buffer, sizeof(Head)); // 拷贝数据头进总的缓冲区 + + int len_rest = len_total - sizeof(Head); + while (len_rest > 0) { // 保证数据体能够全部收到 + len_recv = recv(client, buffer_all + (len_total - len_rest), len_rest, 0); + len_rest -= len_recv; + } + + // 正常 + //m_clientMap[client] = HEART_CHECK_TIMES; // 重置心跳阈值 + + int type = *(int*)buffer; + if (type == 110) { + /*TestSturct2* ts2 = (TestSturct2*)buffer_all; // 转换时,使用总的buffer_all + if (ts2) { + ts2->a = (char*)ts2 + sizeof(TestSturct2); + ts2->b = ts2->a + strlen(ts2->a) + 1; + cout << ts2->len; + cout << "内容1: " << ts2->a << endl; + cout << "内容2: " << ts2->b << endl; + }*/ + } + /*else if (type == LOGIN_REQ) { + // 登录请求 + LoginReq* req = (LoginReq*)buffer_all; // 转换时,使用总的buffer_all + cout << "用户信息:" << req->user_name << " " << req->password << endl; + Login login; + login.business(req, client); // 调用业务处理API + }*/ + if (type == HEART_CHECK_REQ) { + // 收到心跳请求包,回响应包 + HeartCheckRes res; + send(client, (char*)&res, res.len, 0); + cout << "已回复包!" << endl; + } + + // 原封不动的回包 + //send(client, buffer_all, len_total, 0); + + // 用完了,记得释放动态开辟的内存 + if (buffer) + { + delete[] buffer; + buffer = nullptr; // 防止指针悬空,而产生悬空指针 + } + if (buffer_all) { + delete[] buffer_all; + buffer_all = nullptr; + } + + } +} + +void ServerSocket::heartBeatThread(SOCKET client) +{ + while (true) + { + Sleep(HEARTBEAT_INTERVAL * 1000); + mutex heartLock; + lock_guard<std::mutex> lock(heartLock); + --m_clientMap[client]; + + } +} + +void ServerSocket::mMapInsert(SOCKET client) +{ + lock_guard<mutex> lg(m_mutex); + m_clientMap.insert(make_pair(client, HEART_CHECK_TIMES)); + cout << "插入成功:times = " << m_clientMap[client] << endl; +} + +void ServerSocket::mMapUpdate(SOCKET client) +{ + lock_guard<mutex> lg(m_mutex); + m_clientMap.insert(make_pair(client, HEART_CHECK_TIMES)); +} + +void ServerSocket::mMapDelete() +{ + while (true) + { + Sleep(HEARTBEAT_INTERVAL * 1000); + lock_guard<std::mutex> lock(m_mutex); + for (auto& client_socket : m_clientMap) { + cout << client_socket.second << endl; + if (client_socket.second <= 0) { + closesocket(client_socket.first); + m_clientMap.erase(client_socket.first); + cout << "删除连接成功" << endl; + } + } + } +} diff --git "a/GroupB_\351\251\254\345\226\234\351\276\231/Server/\351\251\254\345\226\234\351\276\231/code/face_painting_socket_server/ServerSocket.h" "b/GroupB_\351\251\254\345\226\234\351\276\231/Server/\351\251\254\345\226\234\351\276\231/code/face_painting_socket_server/ServerSocket.h" new file mode 100644 index 0000000..e818f09 --- /dev/null +++ "b/GroupB_\351\251\254\345\226\234\351\276\231/Server/\351\251\254\345\226\234\351\276\231/code/face_painting_socket_server/ServerSocket.h" @@ -0,0 +1,70 @@ +#pragma once +#include <WinSock2.h> +#include <iostream> +#include <map> +#include <thread> +#include <mutex> +#include "ThreadPool.hpp" +#pragma comment(lib,"ws2_32.lib") + +#define PORT 9527 +#define HEART_CHECK_REQ 101 +#define HEART_CHECK_RES 102 +#define HEART_CHECK_TIMES 6 +#define HEARTBEAT_INTERVAL 2 + + + +using namespace std; + +struct Head +{ + int type; // 区分不同功能类型 + int len; // 表示整个封包的长度,是为了后面处理粘包问题的 +}; + +// 间隔:5秒,阈值为6,递减从6开始,到0或小于0 断开/重连 +// 心跳请求包 +struct HeartCheckReq +{ + int type; + int len; + HeartCheckReq() + { + type = 101; + len = sizeof(HeartCheckReq); + } +}; + +// 心跳响应包 +struct HeartCheckRes +{ + int type; + int len; + HeartCheckRes() + { + type = 102; + len = sizeof(HeartCheckRes); + } +}; + +class ServerSocket +{ +public: + ServerSocket(); + virtual ~ServerSocket(); + + bool initSocket(); + void acceptThread(); + void recvAndSendThread(SOCKET client); + void heartBeatThread(SOCKET client); + + void mMapInsert(SOCKET client); + void mMapUpdate(SOCKET client); + void mMapDelete(); +private: + SOCKET m_server; + map<SOCKET, int> m_clientMap; + mutex m_mutex; +}; + diff --git "a/GroupB_\351\251\254\345\226\234\351\276\231/Server/\351\251\254\345\226\234\351\276\231/code/face_painting_socket_server/ThreadPool.hpp" "b/GroupB_\351\251\254\345\226\234\351\276\231/Server/\351\251\254\345\226\234\351\276\231/code/face_painting_socket_server/ThreadPool.hpp" new file mode 100644 index 0000000..a2986bc --- /dev/null +++ "b/GroupB_\351\251\254\345\226\234\351\276\231/Server/\351\251\254\345\226\234\351\276\231/code/face_painting_socket_server/ThreadPool.hpp" @@ -0,0 +1,147 @@ +#pragma once +#include <iostream> +#include <mutex> +#include <atomic> +#include <condition_variable> +#include <queue> +#include <string> + +using namespace std; + +template<typename Task, const size_t DEFAULT_THREAD_NUM, const size_t MAX_THREAD_NUM> +class ThreadPool +{ +public: + ThreadPool() = delete; + ThreadPool(const ThreadPool&) = delete; + ThreadPool& operator=(const ThreadPool&) = delete; + ThreadPool(ThreadPool&&) = delete; + ThreadPool& operator=(ThreadPool&&) = delete; + + explicit ThreadPool(uint32_t timeout) :m_timeout(timeout), m_needRun(true) + { + for (int i = 0; i < DEFAULT_THREAD_NUM; i++) + { + thread([this] { RunTask(); }).detach(); + } + } + ~ThreadPool() { + m_needRun = false; + while (m_runningThreadNum > 0) + { + m_needRunCondition.notify_all(); + } + + } + void Push(Task& task) { + PushTask(task); + if (m_runningThreadNum < MAX_THREAD_NUM && m_idleThreadNum == 0) + { + thread([this] { RunTask(); }).detach(); + } + m_needRunCondition.notify_all(); + } +private: + bool IsQueueEmpty() { + lock_guard<mutex> lg(m_mutex); + return m_taskQueue.empty(); + } + bool GetTask(Task& task) { + lock_guard<mutex> lg(m_mutex); + if (m_taskQueue.empty()) + { + return false; + } + task = m_taskQueue.top(); + m_taskQueue.pop(); + return true; + } + class NumWrapper + { + public: + NumWrapper() = delete; + NumWrapper(atomic<uint32_t>& num) :m_num(num) { m_num++; } + ~NumWrapper() { m_num--; } + + private: + atomic<uint32_t>& m_num; + }; + + void Sleep() { + mutex needRunMutex; + unique_lock<mutex> lock(needRunMutex); + + NumWrapper idleWraper(m_idleThreadNum); + (void)idleWraper; + + m_needRunCondition.wait_for(lock, std::chrono::seconds(m_timeout), + [this] { return !m_needRun || !IsQueueEmpty(); }); + } + void PushTask(const Task& task) { + lock_guard<mutex> lg(m_mutex); + m_taskQueue.push(task); + } + void RunTask() { + NumWrapper runWraper(m_runningThreadNum); + (void)runWraper; + + while (m_needRun) + { + Task task; + if (GetTask(task)) + { + task.Execute(); + continue; + } + Sleep(); + + if (!m_needRun) + { + return; + } + if (GetTask(task)) + { + task.Execute(); + continue; + } + if (m_runningThreadNum > DEFAULT_THREAD_NUM) + { + return; + } + } + } + +private: + atomic<uint32_t> m_idleThreadNum; + atomic<uint32_t> m_runningThreadNum; + atomic_bool m_needRun; + + mutex m_mutex; + condition_variable m_needRunCondition; + uint32_t m_timeout; + priority_queue<Task> m_taskQueue; +}; + +class Task +{ +public: + Task() :m_priority(0) {}; + explicit Task(string context) :m_priority(0) { + m_context = context; + } + + bool operator<(const Task& t) const { + return m_priority < t.m_priority; + } + + void Execute() { + lock_guard<mutex> lg(m_mutex); + cout << "Task is executed,name is" << m_context << endl; + } + +public: + uint32_t m_priority; +private: + string m_context; + static mutex m_mutex; +}; \ No newline at end of file diff --git "a/GroupB_\351\251\254\345\226\234\351\276\231/Server/\351\251\254\345\226\234\351\276\231/code/face_painting_socket_server/face_painting_socket_server.sln" "b/GroupB_\351\251\254\345\226\234\351\276\231/Server/\351\251\254\345\226\234\351\276\231/code/face_painting_socket_server/face_painting_socket_server.sln" new file mode 100644 index 0000000..079f4ad --- /dev/null +++ "b/GroupB_\351\251\254\345\226\234\351\276\231/Server/\351\251\254\345\226\234\351\276\231/code/face_painting_socket_server/face_painting_socket_server.sln" @@ -0,0 +1,28 @@ +锘� +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35521.163 d17.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "face_painting_socket_server", "face_painting_socket_server.vcxproj", "{8F47EF20-7DBA-475C-ABA7-C468E46049F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8F47EF20-7DBA-475C-ABA7-C468E46049F2}.Debug|x64.ActiveCfg = Debug|x64 + {8F47EF20-7DBA-475C-ABA7-C468E46049F2}.Debug|x64.Build.0 = Debug|x64 + {8F47EF20-7DBA-475C-ABA7-C468E46049F2}.Debug|x86.ActiveCfg = Debug|Win32 + {8F47EF20-7DBA-475C-ABA7-C468E46049F2}.Debug|x86.Build.0 = Debug|Win32 + {8F47EF20-7DBA-475C-ABA7-C468E46049F2}.Release|x64.ActiveCfg = Release|x64 + {8F47EF20-7DBA-475C-ABA7-C468E46049F2}.Release|x64.Build.0 = Release|x64 + {8F47EF20-7DBA-475C-ABA7-C468E46049F2}.Release|x86.ActiveCfg = Release|Win32 + {8F47EF20-7DBA-475C-ABA7-C468E46049F2}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git "a/GroupB_\351\251\254\345\226\234\351\276\231/Server/\351\251\254\345\226\234\351\276\231/code/face_painting_socket_server/main.cpp" "b/GroupB_\351\251\254\345\226\234\351\276\231/Server/\351\251\254\345\226\234\351\276\231/code/face_painting_socket_server/main.cpp" new file mode 100644 index 0000000..7f17ae5 --- /dev/null +++ "b/GroupB_\351\251\254\345\226\234\351\276\231/Server/\351\251\254\345\226\234\351\276\231/code/face_painting_socket_server/main.cpp" @@ -0,0 +1,39 @@ +#include <iostream> +#include "ServerSocket.h" +#include "ThreadPool.hpp" +using namespace std; + +#define DEFAULT_THREAD_NUM 3 +#define MAX_THREAD_NUM 6 +#define TIME_OUT 500 +mutex Task::m_mutex; + +int main() { + ServerSocket server1; + string cmd; + while (cin>>cmd) + { + if (cmd == "quit") { + break; + } + } + + /*ThreadPool<Task, DEFAULT_THREAD_NUM, MAX_THREAD_NUM> threadPool_(TIME_OUT); + Task task1("name_1"); + Task task2("name_2"); + Task task3("name_3"); + Task task4("name_4"); + + task4.m_priority = 4; + task3.m_priority = 8; + task2.m_priority = 2; + task1.m_priority = 5; + + threadPool_.Push(task1); + threadPool_.Push(task2); + threadPool_.Push(task3); + threadPool_.Push(task4);*/ + + system("pause"); + return 0; +} \ No newline at end of file -- Gitblit v1.8.0