码蚁0817班级,AI项目,脸谱,双团队架构,赛马机制
hjz
2024-12-04 06095ace67ceeeb1a53faea3565bccdee5fd31b2
Merge branch 'master' of ssh://115.28.86.8:29418/~admin/脸谱AI_0817_1202
10个文件已添加
471 ■■■■■ 已修改文件
GroupB_马喜龙/Public/脸谱-编码规范-B组.docx 补丁 | 查看 | 原始文档 | blame | 历史
GroupB_马喜龙/Public/脸谱-设计说明书-B组.docx 补丁 | 查看 | 原始文档 | blame | 历史
GroupB_马喜龙/Public/脸谱-项目计划表-B组.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
GroupB_马喜龙/Public/脸谱-项目需求分析文档-B组.docx 补丁 | 查看 | 原始文档 | blame | 历史
GroupB_马喜龙/Public/脸谱-风险控制表-B组.docx 补丁 | 查看 | 原始文档 | blame | 历史
GroupB_马喜龙/Server/马喜龙/code/face_painting_socket_server/ServerSocket.cpp 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
GroupB_马喜龙/Server/马喜龙/code/face_painting_socket_server/ServerSocket.h 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
GroupB_马喜龙/Server/马喜龙/code/face_painting_socket_server/ThreadPool.hpp 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
GroupB_马喜龙/Server/马喜龙/code/face_painting_socket_server/face_painting_socket_server.sln 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
GroupB_马喜龙/Server/马喜龙/code/face_painting_socket_server/main.cpp 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
GroupB_ÂíϲÁú/Public/Á³Æ×-±àÂë¹æ·¶-B×é.docx
Binary files differ
GroupB_ÂíϲÁú/Public/Á³Æ×-Éè¼ÆËµÃ÷Êé-B×é.docx
Binary files differ
GroupB_ÂíϲÁú/Public/Á³Æ×-ÏîÄ¿¼Æ»®±í-B×é.xlsx
Binary files differ
GroupB_ÂíϲÁú/Public/Á³Æ×-ÏîÄ¿ÐèÇó·ÖÎöÎĵµ-B×é.docx
Binary files differ
GroupB_ÂíϲÁú/Public/Á³Æ×-·çÏÕ¿ØÖƱí-B×é.docx
Binary files differ
GroupB_ÂíϲÁú/Server/ÂíϲÁú/code/face_painting_socket_server/ServerSocket.cpp
New file
@@ -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;
            }
        }
    }
}
GroupB_ÂíϲÁú/Server/ÂíϲÁú/code/face_painting_socket_server/ServerSocket.h
New file
@@ -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;
};
GroupB_ÂíϲÁú/Server/ÂíϲÁú/code/face_painting_socket_server/ThreadPool.hpp
New file
@@ -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;
};
GroupB_ÂíϲÁú/Server/ÂíϲÁú/code/face_painting_socket_server/face_painting_socket_server.sln
New file
@@ -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
GroupB_ÂíϲÁú/Server/ÂíϲÁú/code/face_painting_socket_server/main.cpp
New file
@@ -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;
}