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