5.4.3 客户端类

5.6.3 数据接收线程   RecvDataThread()函数接收服务器发送的数据结果,并负责通知主线程显示该结果。该函数以客户端连接状态bConnecting变量为while语句循环条件。当套结字缓冲区无数据时,recv()函数立即返回,并返回WSAEWOULDBLOCK错误代码。执行continue语句,继续调用recv()函数接收数据结果。当套结字缓冲区有数据时,recv()函数返回读入数据的长度。在 阅读详情

  客户端CClient类对每个接受的客户端,为其实现接收数据、计算数据和发送计算结果的功能。

1.CClient类的声明

在该类声明如下成员变量。

q        m_socket,接受客户端套接字。该套接字继承了sServer套接字的非阻塞模式属性,作为参数调用recv()和send()函数,实现与客户端的数据发送和接收。

q        m_addr,接受客户端的地址。

q        m_data,客户端数据。接收线程和发送数据线程公用该数据变量。

q        m_hEvent,事件对象。当接收线程完成算数表达式的计算后使用该事件对象,通知发送线程发送数据。

q        m_hThreadSend,发送数据线程句柄。

q        m_hThreadRecv,接收数据线程句柄。

q        m_cs,临界区对象。确保接收数据线程和发送数据线程对m_data数据成员的互斥访问。

q        m_bConning,客户端连接状态。

q        m_bExit,线程退出。

该类声明如下成员函数。

q        CClient(),构造函数。以套接字和客户端地址为参数。

q        ~CClient(),析构函数。

q        CClient(),默认构造函数。

q        StartRuning(),创建发送和接收数据线程。

q        HandleData(),计算表达式结果。

q        IsExit (),接收和发送线程是否已经退出。

q        IsConning(),判断与客户端连接状态。

q        DisConning(),断开与客户端连接。

q        RecvDataThread(),接收客户端的数据。

q        SendDataThread(),向客户端发送数据。

CClient类的声明如下。

class CClient

{

public:

         CClient(const SOCKET sClient,const sockaddr_in &addrClient);

         virtual ~CClient();

 

public:

         BOOL                 StartRuning(void);                                                             //创建发送和接收数据线程

         void                     HandleData(const char* pExpr);                                    //计算表达式

         BOOL                 IsConning(void){                                                               //是否连接存在

                                     return m_bConning;

                                     }

         void                     DisConning(void){                                                            //断开与客户端的连接

                                     m_bConning = FALSE;

                                     }

         BOOL                 IsExit(void){                                                                        //接收和发送线程是否已经退出

                                     return m_bExit;

                                     }

 

public:

         static DWORD __stdcall   RecvDataThread(void* pParam);                //接收客户端数据

         static DWORD __stdcall   SendDataThread(void* pParam);               //向客户端发送数据

 

private:

         CClient();

private:

         SOCKET            m_socket;                                                                                    //套接字

         sockaddr_in     m_addr;                                                                              //地址

         DATABUF m_data;                                                                              //数据

         HANDLE            m_hEvent;                                                                          //事件对象

         HANDLE            m_hThreadSend;                                                             //发送数据线程句柄

         HANDLE            m_hThreadRecv;                                                              //接收数据线程句柄

         CRITICAL_SECTION m_cs;                                                                       //临界区对象

         BOOL                 m_bConning;                                                                    //客户端连接状态

         BOOL                 m_bExit;                                                                              //线程退出

};

2.构造函数和析构函数

该类声明了两个构造函数。默认构造函数生命为private类型,没有实现。另一个构造函数以接受的套接字和客户端地址为参数。在该构造函数中完成初始化成员变量,创建事件对象,初始化临界区的功能。构造函数程序清单如下。

CClient::CClient(const SOCKET sClient, const sockaddr_in &addrClient)

{

         //初始化变量

         m_hThreadRecv = NULL;

         m_hThreadSend = NULL;

         m_socket = sClient;

         m_addr = addrClient;

         m_bConning = FALSE;

         m_bExit = FALSE;

         memset(m_data.buf, 0, MAX_NUM_BUF);

         m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);  //手动设置信号状态,初始化为无信号状态

         InitializeCriticalSection(&m_cs);                                            //初始化临界区

}

在析构函数中,清理在占用的资源。包括关闭接受的套接字,释放保护数据的临界区对象,释放事件对象。程序清单如下。

CClient::~CClient()

{

         closesocket(m_socket);                      //关闭套接字

         m_socket = INVALID_SOCKET;        //套接字无效

         DeleteCriticalSection(&m_cs);          //释放临界区对象

         CloseHandle(m_hEvent);                            //释放事件对象

}

3.创建接收数据和发送数据线程

StartRuning()函数实现创建接收数据线程和发送数据线程。在调用CreateThread函数时,以this作为该函数的第四个参数。这样就将该实例的地址传递给RecvDataThread()函数和SendDataThread()函数。那么在这两个函数中,就可以通过该地址调用CClient类的成员函数了。在成功创建线程后,调用CloseHandle()函数将该线程句柄的引用记数减1。该函数的程序清单如下。

/*

 * 创建发送和接收数据线程

 */

BOOL CClient::StartRuning(void)

{

         m_bConning = TRUE;                                                     //设置连接状态

 

         //创建接收数据线程

         unsigned long ulThreadId;

         m_hThreadRecv = CreateThread(NULL, 0, RecvDataThread, this, 0, &ulThreadId);

         if(NULL == m_hThreadRecv)

         {

                   return FALSE;

         }else{

                   CloseHandle(m_hThreadRecv);

         }

 

         //创建接收数据线程

         m_hThreadSend =  CreateThread(NULL, 0, SendDataThread, this, 0, &ulThreadId);

         if(NULL == m_hThreadSend)

         {

                   return FALSE;

         }else{

                   CloseHandle(m_hThreadSend);

         }

        

         return TRUE;

}

4.收数据

RecvDataThread()函数实现接收客户端数据。该函数是CClient类的静态成员函数。在该函数中将pParam参数强制转换为CClient类型的指针,这样的转换是合理的。因为pParam参数,是在调用CreateThread()函数时,传递的this指针。这个this指针就是在AcceptThread()函数中调用new,创建CClient类实例的地址。在RecvDataThread()函数中,使用该指针访问CClient类的他成员变量和函数。

RecvDataThread()函数是一个for语句循环体。当pClient->m_bConning值为True时,该函数处于循环状态,不断地接收客户端的数据。当pClient->m_bConning值为FALSE时,结束循环。该客户端的接收数据线程退出。

在该函数中定义了一个临时temp字符数组,长度为MAX_NUM_BUF大小,用于接收数据客户端的数据。以m_socket套接字、temp数组、MAX_NUM_BUF和0为参数,调用recv()函数接收数据。当在接收数据缓冲区内没有可读数据时,recv()函数返回WSAEWOULDBLOCK错误代码。在程序中调用continue语句,继续接收客户端的数据。

因为数据包的包头为4个字节,所以当收到客户端发送的数据时,recv()函数返回值应该为大于4字节的长度。收到客户端的数据后,调用HandleData()函数计算数据,然后调用SetEvent()函数,通知发送数据线程,发送数据。

当客户端关闭了与服务器的连接时,recv()函数返回值为0。程序跳出for循环体,接收数据线程退出。在RecvDataThread()函数返回之前,修改与客户端连接状态m_bConning变量的值为FALSE,并调用SetEvent()函数通知发送数据线程退出。RecvDataThread()函数的程序清单如下。

#define     MAX_NUM_BUF                           48                                 //缓冲区的最大长度

 

/*

 * 接收客户端数据

 */

DWORD  CClient::RecvDataThread(void* pParam)

{

         CClient *pClient = (CClient*)pParam;                                             //客户端对象指针

         int              reVal;                                                                          //返回值

         char temp[MAX_NUM_BUF];                                                    //临时变量

 

         memset(temp, 0, MAX_NUM_BUF);

        

         for (;pClient->m_bConning;)                                                    //连接状态

         {

                   reVal = recv(pClient->m_socket, temp, MAX_NUM_BUF, 0);      //接收数据

                  

                   //处理错误返回值

                   if (SOCKET_ERROR == reVal)

                   {

                            int nErrCode = WSAGetLastError();

 

                            if ( WSAEWOULDBLOCK == nErrCode )                               //接受数据缓冲区不可用

                            {

                                     continue;                                                                             //继续循环

                            }else if (WSAENETDOWN == nErrCode ||                             //客户端关闭了连接

                                                WSAETIMEDOUT == nErrCode ||

                                               WSAECONNRESET == nErrCode )

                            {

                                     break;                                                                                  //线程退出

                            }

                   }

                  

                   //客户端关闭了连接

                   if ( reVal == 0)  

                   {

                            break;

                   }

 

                   //收到数据

                   if (reVal > HEADERLEN)

                   {

                            pClient->HandleData(temp);                                                   //处理数据

 

                            SetEvent(pClient->m_hEvent);                                                //通知发送数据线程

 

                            memset(temp, 0, MAX_NUM_BUF);                                       //清空临时变量

                   }

 

                   Sleep(TIMEFOR_THREAD_CLIENT);                                             //线程睡眠

         }

        

         pClient->m_bConning = FALSE;                                                               //与客户端的连接断开

 

         SetEvent(pClient->m_hEvent);                                                                   //通知发送数据线程退出

 

         return 0;                                                                                                          //退出

}

5.计算数据

在5.2节中定义了发送数据的格式。发送的数据包由包头和数据两部分组成。包头的type字段指明了该数据类型,有消息和算数表达两种。“E”代表算术表达式,“B”代表消息。包头的len字段指明了整个包的长度。客户端和服务器都使用该结构。数据包的定义如下所示。

//数据包类型

#define EXPRESSION                         'E'                        //算数表达式

#define BYEBYE                                   'B'                        //消息byebye,Byebye,OK

#define HEADERLEN                          (sizeof(hdr))      //头长度

 

//数据包头结构,该结构在win32下为4byte

typedef struct _head

{

         char                    type;                                                //类型

         unsigned short          len;                                                 //数据包的长度(包括头的长度)

}hdr, *phdr;

 

//数据包中的数据结构

typedef struct _data

{

         char buf[MAX_NUM_BUF];                                     //数据

}DATABUF, *pDataBuf;

HandleData()函数实现对接收数据计算的功能。当接收的数据是消息时,修改包头的长度,并且用“OK”替换原来的“Byebye”或者“byebye”。最后将包头和消息到m_data变量中。

当接收到算数表达时,对数据的处理过程比较复杂。图为计算算数表达式的过程。

在HandleData()函数中,使用sscanf()函数读取接收数据包中的数字和运算符。使用sprintf()函数将算数表达式和计算结果写入temp临时字符数组。然后,修改数据包头中len值为包头长度与temp字符串长度之和。最后,将temp字符数组中的数据复制到m_data变量中。HandleData()函数的程序清单如下。

/*

 *  计算表达式,打包数据

 */

void CClient::HandleData(const char* pExpr)  

{

         memset(m_data.buf, 0, MAX_NUM_BUF);//清空m_data

        

    //如果是“byebye”或者“Byebye”

         if (BYEBYE == ((phdr)pExpr)->type)

         {

                  EnterCriticalSection(&m_cs);

                   phdr pHeaderSend = (phdr)m_data.buf;                               //发送的数据

                   pHeaderSend->type = BYEBYE;                                             //单词类型

                   pHeaderSend->len = HEADERLEN + strlen("OK");            //数据包长度

                   memcpy(m_data.buf + HEADERLEN, "OK", strlen("OK"));         //复制数据到m_data"

                   LeaveCriticalSection(&m_cs);

 

         }else{//算数表达式

 

                   int nFirNum;                                                                                //第一个数字

                   int nSecNum;                                                                              //第二个数字

                   char cOper;                                                                                  //算数运算符

                   int nResult;                                                                                  //计算结果

                   //格式化读入数据

                   sscanf(pExpr + HEADERLEN, "%d%c%d", &nFirNum, &cOper, &nSecNum);

 

                   //计算

                   switch(cOper)

                   {

                   case '+':                                                                                        //加

                            {

                                     nResult = nFirNum + nSecNum;

                                     break;

                            }

                   case '-':                                                                                         //减

                            {

                                     nResult = nFirNum - nSecNum;

                                     break;

                            }

                   case '*':                                                                                         //乘

                            {

                                     nResult = nFirNum * nSecNum;       

                                     break;

                            }

                   case '/':                                                                                         //除

                            {

                                     if (ZERO == nSecNum)                                          //无效的数字

                                     {

                                               nResult = INVALID_NUM;

                                     }else

                                     {

                                               nResult = nFirNum / nSecNum;       

                                     }

                                     break;

                            }

                   default:

                            nResult = INVALID_OPERATOR;                                  //无效操作符

                            break;

                   }

 

                   //将算数表达式和计算的结果写入字符数组中

                   char temp[MAX_NUM_BUF];

                   char cEqu = '=';

                   sprintf(temp, "%d%c%d%c%d",nFirNum, cOper, nSecNum,cEqu, nResult);

 

                   //打包数据

                   EnterCriticalSection(&m_cs);

                   phdr pHeaderSend = (phdr)m_data.buf;                               //发送的数据

                   pHeaderSend->type = EXPRESSION;                                   //数据类型为算数表达式

                   pHeaderSend->len = HEADERLEN + strlen(temp);           //数据包的长度

                   memcpy(m_data.buf + HEADERLEN, temp, strlen(temp));       //复制数据到m_data

                   LeaveCriticalSection(&m_cs);

 

         }

}

6.发送数据

SendDataThread()函数实现向客户端发送计算表达式结果的功能。该函数在结构上与RecvDataThread()函数结构相似,也是一个for语句的循环体。

在该循环体中,以m_hEvent事件对象句柄和INFINITE为参数调用WaitForSingleObject()函数。该函数只有当接收到发送数据线程的m_hEvent事件通知时,才会返回。当该函数返回时,说明接收数据线程已经完成了对数据的计算。

接下来调用send()函数完成数据的发送。该函数的第一个参数是接收的客户端m_socket套接字,第二个参数是要发送的m_data数据,第三个参数是nSendlen数据长度。当发送缓冲区不可用时,该函数返回WSAEWOULDBLOCK错误代码。在程序中调用continue语句继续发送数据,直到成功为止。

客户端结束请求时,该线程很难发觉到。因为程序阻塞于WaitForSingleObject()函数的调用。然而,接收数据线程可以根据recv()函数的返回值为0,确定客户端已经结束请求。

为防止客户端结束请求时,发送数据线程阻塞于WaitForSingleObject()函数的调用。在接收数据线程退出时,给发送数据线程事件通知,以促使该函数返回。此时,连接状态m_bConning变量值为FALSE,表明客户端已经结束请求,发送数据线程退出。该线程退出时,设置m_bExit变量为TRUE,表明接收和发送数据线程都已经退出。

通过以上程序设计,保证了接收和发送数据线程,在客户端结束请求时安全退出。SendDataThread()函数的程序清单如下。

/*

 * //向客户端发送数据

 */

DWORD CClient::SendDataThread(void* pParam) 

{

         CClient *pClient = (CClient*)pParam;                                   //转换数据类型为CClient指针

 

         for (;pClient->m_bConning;)                                          //连接状态

         {       

                   //收到事件通知

                   if (WAIT_OBJECT_0 == WaitForSingleObject(pClient->m_hEvent, INFINITE))

                   {

                            //当客户端的连接断开时,接收数据线程先退出,然后该线程后退出,并设置退出标志

                            if (!pClient->m_bConning)

                            {

                                     pClient->m_bExit = TRUE;

                                     break ;

                            }

 

                            //进入临界区

                            EnterCriticalSection(&pClient->m_cs);

                            //发送数据

                            phdr pHeader = (phdr)pClient->m_data.buf;

                            int nSendlen = pHeader->len;

 

                            int val = send(pClient->m_socket, pClient->m_data.buf, nSendlen,0);

                            //处理返回错误

                            if (SOCKET_ERROR == val)

                            {

                                     int nErrCode = WSAGetLastError();

                                     if (nErrCode == WSAEWOULDBLOCK)                       //发送数据缓冲区不可用

                                     {

                                               continue;

                                     }else if ( WSAENETDOWN == nErrCode ||

                                                          WSAETIMEDOUT == nErrCode ||

                                                          WSAECONNRESET == nErrCode)        //客户端关闭了连接

                                     {

                                               //离开临界区

                                               LeaveCriticalSection(&pClient->m_cs);

                                               pClient->m_bConning = FALSE;                          //连接断开

                                               pClient->m_bExit = TRUE;                                    //线程退出

                                               break;

                                     }else {

                                               //离开临界区

                                               LeaveCriticalSection(&pClient->m_cs);

                                               pClient->m_bConning = FALSE;                          //连接断开

                                               pClient->m_bExit = TRUE;                                    //线程退出

                                               break;

                                     }

                            }

                            //成功发送数据

                            //离开临界区

                            LeaveCriticalSection(&pClient->m_cs);

                            //设置事件为无信号状态

                            ResetEvent(&pClient->m_hEvent);

                   }

         }

 

         return 0;

}

zookeeper源码阅读分析笔记--客户端服务端通信机制以及session超时、过期处理 zookeeper watch机制的原理分析 阅读详情

相关推荐

python3 利用MT5客户端下载历史数据

运用MT5 官方提供的包MetaTrader5 #!encoding=utf8 from datetime import datetime import matplotlib.pyplot as plt import pandas as pd from pandas.plotting import register_matplotlib_converters register_matplotlib_converters() import MetaTrader5 as mt5 import pytz,.

吕海洋的博客 4380

Linux下C语言CLIENT端实现socket通信并实现断线重连

【代码】Linux下C语言CLIENT端实现socket通信并实现断线重连。

Sundb1313149的博客 2296

C# Socket通信客户端类、服务器类

其实这些东西网上都有,但是比较凌乱,很少有封装好的类,在此共享一下。。。          一个Socket服务器类,一个Socket客户端类,都可以直接拿去用,下边有详细的调用示例。          需要说明的是,服务器类没有处理多客户连接,只是简单的响应单客户连接。          另外,提醒一点,尤其是很多新手容易犯的错误,就是服务器类处理事务是在线程中进行的,此时不能访问界面上的

杨元的博客 3661

C++ socket UDP网络编程(简单聊天室)

0.通信步骤流程图(左:服务器;右:客户端;) 1.服务器代码 1.1服务器类头文件(CServer_UDP.h) #pragma once #include <winsock2.h> class CServer_UDP { public: CServer_UDP(); void SendMsg(const char sendBuf[]); void Rec...

优快云_WHB的博客 7142

MT4客户端API

登录 请求地址 http://{host}/srv/dologin 参数 名称 类型 必须 说明 server string yes MT4服务器地址 login int yes Mt4帐号 password ...

MT4Develop的博客 2060

一文了解ECU软件刷写的2种方法:Bootloader刷写和调试器刷写

分为刷写前、刷写中和刷写后三个阶段,如下示意:下面我们来详细了解一下Bootloader收到外部请求后开始刷写的三个阶段1)刷写前进行刷写的准备,一是确保刷写阶段总线通信的稳定性,二是避免刷写阶段出现非预期的故障,三是读取车辆数据供刷写前的一些检查等,如下所示:首先进行会话控制,通过功能寻址方式进入扩展会话模式,为后面的信息访问及其他指令做准备;然后检查刷写的前提条件,通过物理寻址方式发送历程控制请求。比如车确实处于静止状态,供电电压稳定等条件下才允许刷写;

menghuyouyou的博客 5784

TcpClient类介绍[3-1]

TcpClient.h #ifndef MUDUO_NET_TCPCLIENT_H #define MUDUO_NET_TCPCLIENT_H #include #include #include namespace muduo { namespace net { class Connector; typedef boost::share

阳光梦的专栏 1064

Windows Server 2019/2022 RDS 授权实战:3步激活许可证服务器,解决120天宽限期问题

本文详细介绍了Windows Server 2019/2022 RDS授权实战,提供3步激活许可证服务器的完整解决方案,解决120天宽限期问题。涵盖远程桌面授权服务器配置、许可证激活方法及组策略设置,确保企业合规使用远程桌面服务。

weixin_32705179的博客 978

TCP批量文件传输服务端与客户端(二)----客户端接收端

#ifndef _TCP_NET_SHARE_CLIENT_H__ #define _TCP_NET_SHARE_CLIENT_H__ #include &lt;iostream&gt; #include &lt;vector&gt; #include &lt;map&gt; #include "sysfun.h" #define MAX_BUFFER 65535 #define PACKSI...

CHNIM的博客 997

Win10网络图标消失,网络图标变成灰色,打开网络设置闪退等问题解决

介绍 主要解决如下问题 网络图标消失 常用方法配置中出现的网络图标变成灰色没有办法打开 打开网络和Internet闪退 错误提示`网络发现已关闭。网络计算机和设备不可见。请启动网络和共享中心的网络发现。 连不上网,诊断结果为 依赖服务或组无法启动 这个问题大概率通过重装系统不能解决,请大家谨慎测试之后最后选择重装这个路线。 方法1:这一步一定要做(卸载三方软件) 把360安全卫士,软件管家这些东西都卸载掉。 我的问题一开始就是这个软件引起的,可能他检测到我还给台式机配了无线网卡,然后就把有线网络的一些

呆呆象呆呆的博客 3万+

鱼鹰优化算法(OOA)详解:从猛禽捕食智能到优化算法实现

鱼鹰优化算法(Osprey Optimization Algorithm, OOA)是2023年提出的一种新型元启发式优化算法,灵感来源于鱼鹰(一种中型猛禽)高效的捕食策略。算法模拟了鱼鹰从空中识别水下鱼类位置并俯冲捕食,然后将捕获的鱼带至安全位置享用的全过程,以此抽象出全局探索和局部开发两个核心阶段。OOA算法具有参数少、结构简单、收敛速度快、全局寻优能力强等特点。自提出以来,已在函数优化、机器学习参数调优(如CatBoost模型)、路径规划等多个领域展现出良好性能,为解决复杂优化问题提供了新的有效工具。

qq_42212808的博客 273

5.4.3 客户端类

  客户端CClient类对每个接受的客户端,为其实现接收数据、计算数据和发送计算结果的功能。1.CClient类的声明在该类声明如下成员变量。q        m_socket,接受客户端套接字。该套接字继承了sServer套接字的非阻塞模式属性,作为参数调用recv()和send()函数,实现与客户端的数据发送和接收。q        m_addr,接受客户端的地址。q  

647

从零开始学习CANoe(十六)—— Graphics

Graphics是一种以时间轴为横坐标,符号值为纵坐标的显示分析方法,相对于Trace来说,更直观的观察出信号的跳变

蚂蚁小兵 9193

zookeeper3.5.4源码环境搭建

zookeeper3.5.4源码环境搭建 1. 准备工作 渠道 地址 官网 zk源码下载地址 网盘 zk源码下载地址 提取码:5555 注意:因为zookeeper是由ant来构建的,所以需要使用ant命令来转换成工程,然后导入idea(当前提供的下载地址无需进行转换操作,下载完毕后直接导入idea即可) 2. idea导入源码 3. 服务器端启动程序配置 启动服务端运行主类org.apache.zookeeper.server.QuorumPeerMain,将zoo.cfg

chuanchengdabing的博客 629

188、LLC谐振变换器的样机调试实战(EMI测试)

本文分享了LLC谐振变换器EMI调试的实战经验。作者通过300W电源案例,指出LLC的EMI问题主要来自谐振腔共模电流和死区振铃,并提出三板斧解决方案:优化功率回路布局、合理选择共模电感、正确配置X/Y电容。文章详细分析了谐振电容位置、MOSFET走线、变压器屏蔽等关键设计要点,并列举示波器探头、滤波器接地等常见误区。最后强调EMI调试70%依赖布局优化,建议预扫测试、数据记录并保留6dB余量。全文以实际案例贯穿,为LLC电源EMI设计提供了实用指导。

Jack010169的博客 55

基于YOLO的印章检测及文字识别

针对印章自动化检测与文字识别需求,提出了一种融合改进YOLO模型与OCR技术的端到端解决方案,旨在解决复杂背景干扰、印章残缺变形及环形文字排列等难题

商务合作 / 项目定制 / 学习交流。个人vx:lovely_wml 8221

MQTTnet实现客户端连接

MQTT连接服务核心类:业务需求是一个客户端对应的一个MQTT服务,因此按照服务端个数创建对应的客户端连接,实现通过每一个服务端订阅消息,获取数据。如下图所示,开启3个客户端连接3个服务端,当其一个服务端出现异常(服务停止,网络异常无法连接)导致连接断开时,实现每5秒连接一次。连接信息model类。

CONSOLE11的博客 2512

YOLOv11【第二章:核心模块进阶篇·第3节】LDConv线性可变形卷积改进YOLOv11!

🏆 本文收录于专栏 《YOLOv11实战:从入门到深度优化》。本专栏围绕 YOLOv11 的改进、训练、部署与工程优化 展开,系统梳理并复现当前主流的 YOLOv11 实战案例与优化方案,内容目前已覆盖 分类、检测、分割、追踪、关键点、OBB 检测 等多个方向。

**My Coding Family** 7440

Kafka 2.5.0 SASL/PLAIN 认证配置:4个关键配置文件与3类用户权限实战

本文详细解析Kafka 2.5.0版本中SASL/PLAIN安全认证的配置方法,通过四个关键配置文件和三类用户权限的实战演示,帮助开发者构建生产级的安全防护体系。内容涵盖JAAS身份认证配置、server.properties安全参数设置、客户端配置文件模板以及权限控制实战操作,适用于需要用户密码登录的内部系统或测试环境。

weixin_33976072的博客 448

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Eclipse3.2.1+jboss4.0.5开发J2EE中的EJB(无状态会话Bean 附图)

软件配置:Eclipse3.2.1+jboss4.0.5+jbosside1.6.0+xdoclet1.2.3+lomboz1,启动Eclipse,打开首选项,选择xdoclet,并进行设置,如图1-1所示:   图1-1设置前请先下载xdoclet-bin-1.2.3.zip,并解压到相关目录.2,新建server, 选择JBoss下的JBoss v4.0,其他缺省,单击完成.在右下角Ser

blue_fire2008的专栏 1160

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

【企业级向量安全红线】:EF Core 10中必须禁用的5个默认配置、4类危险LINQ表达式及3种合规审计Checklist

为企业级向量搜索提供Entity Framework Core 10向量搜索扩展安全性最佳方案,禁用5个高危默认配置、规避4类危险LINQ表达式,落地3种合规审计Checklist。适用于金融、医疗等强监管场景,兼顾性能与GDPR/等保要求,值得收藏。

LogicGap的博客 135

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

httpClientWithMD5

package com.fintech.common; import com.alibaba.fastjson.JSON; import com.fintech.entity.CreateEnterPriseReq; import com.fintech.entity.CreateEnterPriseResp; import com.fintech.httputil.*; imp...

weixin_30518397的博客 121

若依4.7.8(springboot2.5.15)升级到4.8.1(springboot3.3.5)并集成Dubbo3客户端

本文讲解若依4.7.8(springboot2.5.15)升级到4.8.1(springboot3.3.5)并集成Dubbo3客户端,同时使用nacos做服务发现的实现过程。深入浅出。

搬砖工 1584

03单点登录CAS5.3.4集成客户端

参照网址 参照网址 server代码地址 client1代码地址 client2代码地址 之前一直是server端登录验证。所谓单点登录(SSO),只当企业用户同时访问多个不同(类型的)应用时,他们只需要提供自身的用户凭证信息(比如用户名/密码)一次,当用户在不同的应用间切换时,他们不用再重复地输入自身的用户凭证了。所以此章写一下cas如何整合客户端 1.配置Host #cas服务端 127.0....

Amy的博客 1483

小白笔记之 客户端SVN的使用;配置VS 2019+Qt 5.9+OpenCV 4.5.3;华为 Atlas 200DK 入门

一、客户端SVN的使用;二、配置Visual Studio 2019+Qt 5.9+OpenCV 4.5.3;三、华为 Atlas 200DK 入门

头发浓密的萌新的博客 1092

Zabbix 5.4客户端安装

通过前面的操作,相信大家的zabbix server已经能够正常的运行起来了,但是仅有zabbix server是不完整的,server的目标是监控其他的主机,而并非只监控自身,所以我们还需要在要做监控的主机上安装zabbix client。 操作系统: centos 7 客户端: zabbix 5.4 agent 1.安装客户端 在官网选择对应的客户端版本。 大家根据自己系统的版本,以及前面安装的zabbix server的具体版本进行组合。 前面我的server是5.4,所以这里我的客户端agent也

alfiy的专栏 1403
上一篇: 5.4.2接受客户端请求线程
下一篇: 5.4.4清理资源线程
VCSockets
博客等级 码龄19年 45粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值