开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 1589|回复: 32
收起左侧

[易语言纯源码] ETCP C++ 代码第二集 修复一些bug 和变量教科书级

[复制链接]
头像被屏蔽
结帖率:100% (4/4)
发表于 2024-7-1 13:19:53 | 显示全部楼层 |阅读模式   安徽省合肥市
分享源码
界面截图: -
是否带模块: -
备注说明: -
本帖最后由 盖伦总管 于 2024-7-1 14:04 编辑

还是老方法 g++ -shared -o WinSocket.dll WinSocket.cpp WinSocket.def -lws2_32 编译
遇到问题可以加Q 481261965 反馈
下集预告
重写一下配套模式 用Event事件对 同步方法进行处理
未来计划重新设计内存部分 解决内存溢出
增加WebSocket和HTTP协议
与HP_SOCKET 不同的是 用最简单的方法高性能使用 原生TCP
代码重写与优化  


[C++] 纯文本查看 复制代码
#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <WinSock2.h>

#pragma comment(lib, "WS2_32.lib")
#pragma comment(lib, "msvcrt.lib")
#include <stdio.h>
#include <mswsock.h>
#include <MSTcpIP.h>
#include <process.h>

#define tcp_server_connt 1
#define tcp_server_recv 2
#define tcp_server_stop 3
#define tcp_server_send 4
#define tcp_server_close 5

#define tcp_client_connt 1
#define tcp_client_recv 2
#define tcp_client_stop 3
#define tcp_client_send 4
#define tcp_client_close 5

#define tcp_len 65535

typedef void(__stdcall *onServer_ex)(HANDLE Server, SOCKET so, int type, char *buf, int len, int count);
typedef void(__stdcall *onClient_ex)(HANDLE Client, SOCKET so, int type, char *buf, int len);

extern int g_cpu;
extern int buf_len;

extern HANDLE hEvent_Server;
extern HANDLE hEvent_Client;

extern onServer_ex onServerFunc;
extern onClient_ex onClientFunc;

HANDLE hEvent_Server = NULL;
HANDLE hEvent_Client = NULL;
int g_cpu = 0;
int buf_len = 512;
onServer_ex onServerFunc = NULL;
onClient_ex onClientFunc = NULL;

int closesockets(SOCKET so);
int closesockets(SOCKET so)
{
        if (INVALID_SOCKET == so)
        {
                return 0;
        }
        struct linger lingerStruct;
        lingerStruct.l_onoff = 1;
        lingerStruct.l_linger = 0;
        setsockopt(so, SOL_SOCKET, SO_LINGER, (char *)&lingerStruct, sizeof(lingerStruct));
        shutdown(so, SD_BOTH);
        return closesocket(so);
}
bool __stdcall socket_local(char *ip)
{
        char hostname[256];
        int ret = gethostname(hostname, sizeof(hostname));
        if (ret == SOCKET_ERROR)
        {
                return false;
        }
        HOSTENT *host = gethostbyname(hostname);
        if (host == NULL)
        {
                return false;
        }
        strcpy(ip, inet_ntoa(*(in_addr *)*host->h_addr_list));
        return true;
}

class Socket_Server_IO;
// 定义一个结构体用于存储服务器信息
typedef struct server_struct
{
        OVERLAPPED op;                                         // OVERLAPPED结构用于异步I/O
        Socket_Server_IO *so;                         // 指向服务器对象的指针
        int state;                                                 // 服务器连接的状态
        SOCKET c_socket;                                 // 客户端套接字
        char *buf;                                                 // 数据缓冲区
        DWORD slen;                                                 // 接收数据的长度
        DWORD cb;                                                 // 传输的字节数
        DWORD bufSize;                                         // 缓冲区大小
        DWORD bufOffset;                                 // 缓冲区的偏移量
} S_server_struct, *P_server_struct; // 定义结构体指针类型

class Socket_Server_IO
{
public:
        Socket_Server_IO(void);
        ~Socket_Server_IO(void);

public:
        int Init(char *host, unsigned short nPort, int nIsSC);
        int AcceptServer();
        int Accept();
        void ClientAccept(bool error, P_server_struct op);
        void RecvData(bool error, P_server_struct op);
        int Close();
        int doSend(SOCKET so, char *buf, DWORD cb);
        int doSend_sync(SOCKET so, char *buf, DWORD cb);
        void OnSend(bool ercode, P_server_struct op);
        char *get_ip(SOCKET so)
        {
                sockaddr_in in;
                int len = sizeof(in);
                getpeername(so, (sockaddr *)&in, &len);
                return inet_ntoa(in.sin_addr);
        }
        SOCKET get_socket()
        {
                return m_hSocket;
        }
        u_short get_port()
        {
                sockaddr_in in;
                int len = sizeof(in);
                getsockname(m_hSocket, (sockaddr *)&in, &len);
                return ntohs(in.sin_port);
        }
        char *get_addr(SOCKET m_hSocket)
        {
                sockaddr_in in;
                int len = sizeof(in);
                getsockname(m_hSocket, (sockaddr *)&in, &len);
                return inet_ntoa(in.sin_addr);
        }

public:
        SOCKET m_hSocket;
        int m_count;
        CRITICAL_SECTION m_token;
        BOOL m_mate;
        BOOL m_stop;
};

Socket_Server_IO::Socket_Server_IO(void)
{
        m_stop = FALSE;
        InitializeCriticalSection(&m_token);
        m_count = 0;
        m_hSocket = INVALID_SOCKET;
}
Socket_Server_IO::~Socket_Server_IO(void)
{
        m_count = 0;
        m_hSocket = INVALID_SOCKET;
}
int Socket_Server_IO::Init(char *host, unsigned short nPort, int nIs)
{
        // 设置成员变量m_mate
        m_mate = nIs;

        // 创建一个重叠模式的套接字
        m_hSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED);
        if (INVALID_SOCKET == m_hSocket)
        {
                // 如果创建套接字失败,返回错误码
                return WSAGetLastError();
        }

        // 将套接字关联到一个I/O完成端口
        HANDLE t = CreateIoCompletionPort((HANDLE)m_hSocket, hEvent_Server, 0, 0);
        if (NULL == t)
        {
                // 如果关联失败,关闭套接字并返回错误码
                Close();
                return GetLastError();
        }

        // 初始化sockaddr_in结构体
        sockaddr_in in;
        in.sin_family = AF_INET;
        in.sin_addr.S_un.S_addr = inet_addr(host); // 设置主机地址
        in.sin_port = htons(nPort);                                   // 设置端口号

        // 绑定套接字
        if (SOCKET_ERROR == bind(m_hSocket, (SOCKADDR *)&in, sizeof(in)))
        {
                // 如果绑定失败,关闭套接字并返回错误码
                Close();
                return WSAGetLastError();
        }

        // 开始监听套接字
        if (SOCKET_ERROR == listen(m_hSocket, g_cpu))
        {
                // 如果监听失败,关闭套接字并返回错误码
                Close();
                return WSAGetLastError();
        }

        // 接受客户端连接
        return AcceptServer();
}

int Socket_Server_IO::AcceptServer()
{
        // 为服务器结构分配内存
        server_struct *op = new server_struct;
        // 初始化内存
        memset(op, 0, sizeof(server_struct));
        // 为数据分配缓冲区
        op->buf = new char[buf_len];
        // 设置服务器对象指针
        op->so = this;
        // 设置缓冲区大小和偏移量
        op->bufSize = buf_len;
        op->bufOffset = 0;
        // 设置服务器连接的初始状态
        op->state = tcp_server_connt;
        // 将客户端套接字初始化为无效值
        op->c_socket = INVALID_SOCKET;
        // 创建一个带有重叠I/O的新的套接字
        op->c_socket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED);

        // 如果套接字创建失败,清理并返回错误代码
        if (INVALID_SOCKET == op->c_socket)
        {
                delete[] op->buf;
                op->buf = NULL;
                delete op;
                op = NULL;
                Close();
                return WSAGetLastError();
        }

        // 设置套接字选项
        setsockopt(op->c_socket, SOL_SOCKET, SO_RCVBUF, (const char *)&buf_len, sizeof(int)); // 设置接收缓冲区大小
        // 设置接收缓冲区大小为 buf_len

        int nSendBuf = 0;
        setsockopt(op->c_socket, SOL_SOCKET, SO_SNDBUF, (const char *)&nSendBuf, sizeof(int)); // 设置发送缓冲区大小为 0
        // 设置发送缓冲区大小为 0

        BOOL bReuseaddr = TRUE;
        setsockopt(op->c_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&bReuseaddr, sizeof(BOOL)); // 启用地址重用选项
        // 启用地址重用选项,允许套接字绑定到已在使用中的地址上

        // 创建一个I/O完成端口并将其与套接字关联
        HANDLE t = NULL;
        t = CreateIoCompletionPort((HANDLE)op->c_socket, hEvent_Server, 0, 0);
        // 创建 IO 完成端口,并将 op->c_socket 关联到 hEvent_Server 上进行异步 IO 操作

        if (NULL == t)
        {
                // 如果创建 IO 完成端口失败,则进行以下操作:
                closesocket(op->c_socket);           // 关闭套接字
                op->c_socket = INVALID_SOCKET; // 设置套接字为无效值
                delete[] op->buf;                           // 删除 op 对象中的缓冲区数组
                op->buf = NULL;                                   // 将缓冲区指针置空
                delete op;                                           // 删除 op 对象
                op = NULL;                                           // 将 op 指针置空
                Close();                                           // 调用 Close() 函数(假设该函数用于执行额外的关闭操作)
                return GetLastError();                   // 返回最后的错误代码
        }

        // 获取 AcceptEx 函数指针
        LPFN_ACCEPTEX lpfnAcceptEx = NULL;
        GUID lGUID = WSAID_ACCEPTEX; // 定义 AcceptEx 函数的 GUID
        DWORD cb = 0;

        // 使用 WSAIoctl 函数获取 AcceptEx 函数指针
        if (WSAIoctl(m_hSocket, SIO_GET_EXTENSION_FUNCTION_POINTER, &lGUID, sizeof(GUID), &lpfnAcceptEx, sizeof(lpfnAcceptEx), &cb, NULL, NULL))
        {
                // 如果获取函数指针失败,则进行以下操作:
                closesocket(op->c_socket);           // 关闭套接字
                op->c_socket = INVALID_SOCKET; // 设置套接字为无效值
                delete[] op->buf;                           // 删除 op 对象中的缓冲区数组
                op->buf = NULL;                                   // 将缓冲区指针置空
                delete op;                                           // 删除 op 对象
                op = NULL;                                           // 将 op 指针置空
                Close();                                           // 调用 Close() 函数(假设该函数用于执行额外的关闭操作)
                return 2;                                           // 返回错误代码 2(自定义的错误代码,具体含义由上下文决定)
        }

        // 发出异步 AcceptEx 操作
        DWORD Cb = 0;

        // 调用 lpfnAcceptEx 函数发起异步 AcceptEx 操作
        if (lpfnAcceptEx(m_hSocket, op->c_socket, op->buf, 0, sizeof(sockaddr) + 16, sizeof(sockaddr) + 16, &Cb, (LPOVERLAPPED)op))
        {
                // 如果 AcceptEx 操作失败,则进行以下操作:
                closesocket(op->c_socket);           // 关闭套接字
                op->c_socket = INVALID_SOCKET; // 设置套接字为无效值
                delete[] op->buf;                           // 删除 op 对象中的缓冲区数组
                op->buf = NULL;                                   // 将缓冲区指针置空
                delete op;                                           // 删除 op 对象
                op = NULL;                                           // 将 op 指针置空
                Close();                                           // 调用 Close() 函数(假设该函数用于执行额外的关闭操作)
                return 3;                                           // 返回错误代码 3(自定义的错误代码,具体含义由上下文决定)
        }

        // 如果一切顺利,返回0
        return 0;
}
int Socket_Server_IO::Close()
{
        m_stop = TRUE;
        m_count = 0;
        closesockets(m_hSocket);

        m_hSocket = INVALID_SOCKET;
        return 0;
}

int Socket_Server_IO::Accept()
{
        // 分配并初始化一个 server_struct 结构体
        server_struct *op = new server_struct;
        memset(op, 0, sizeof(server_struct));

        // 分配缓冲区,存储接收的数据
        op->buf = new char[buf_len];
        op->so = this;                                  // 保存当前 Socket_Server_IO 对象的指针
        op->bufSize = buf_len;                  // 设置缓冲区大小
        op->bufOffset = 0;                          // 初始化缓冲区偏移量为 0
        op->state = tcp_server_connt; // 设置初始状态为 tcp_server_connt

        // 创建一个重叠模式的客户端套接字
        op->c_socket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED);

        // 如果创建客户端套接字失败,释放资源并返回错误码
        if (INVALID_SOCKET == op->c_socket)
        {
                delete[] op->buf; // 释放缓冲区
                op->buf = NULL;
                delete op; // 删除结构体
                op = NULL;
                return WSAGetLastError(); // 返回最后的错误码
        }

        // 设置套接字选项
        setsockopt(op->c_socket, SOL_SOCKET, SO_RCVBUF, (const char *)&buf_len, sizeof(int)); // 设置接收缓冲区大小
        int nSendBuf = 0;
        setsockopt(op->c_socket, SOL_SOCKET, SO_SNDBUF, (const char *)&nSendBuf, sizeof(int)); // 设置发送缓冲区大小为 0
        BOOL bReuseaddr = TRUE;
        setsockopt(op->c_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&bReuseaddr, sizeof(BOOL)); // 启用地址重用选项

        // 将客户端套接字关联到 I/O 完成端口
        HANDLE t = NULL;
        t = CreateIoCompletionPort((HANDLE)op->c_socket, hEvent_Server, 0, 0);
        if (NULL == t)
        {
                closesockets(op->c_socket); // 关闭客户端套接字
                op->c_socket = INVALID_SOCKET;
                PostQueuedCompletionStatus(hEvent_Server, 0, 0, (LPOVERLAPPED)op); // 发送完成状态
                delete[] op->buf;                                                                                                   // 释放缓冲区
                op->buf = NULL;
                delete op; // 删除结构体
                op = NULL;
                return GetLastError(); // 返回最后的错误码
        }

        // 获取 AcceptEx 函数指针
        LPFN_ACCEPTEX lpfnAcceptEx = NULL;
        GUID lGUID = WSAID_ACCEPTEX;
        DWORD cb = 0;
        if (WSAIoctl(m_hSocket, SIO_GET_EXTENSION_FUNCTION_POINTER, &lGUID, sizeof(GUID), &lpfnAcceptEx, sizeof(lpfnAcceptEx), &cb, NULL, NULL))
        {
                closesockets(op->c_socket); // 关闭客户端套接字
                op->c_socket = INVALID_SOCKET;
                PostQueuedCompletionStatus(hEvent_Server, 0, 0, (LPOVERLAPPED)op); // 发送完成状态
                delete[] op->buf;                                                                                                   // 释放缓冲区
                op->buf = NULL;
                delete op; // 删除结构体
                op = NULL;
                return 2; // 返回错误码 2
        }

        // 调用 AcceptEx 函数接受客户端连接
        DWORD Cb = 0;
        if (lpfnAcceptEx(m_hSocket, op->c_socket, op->buf, 0, sizeof(sockaddr) + 16, sizeof(sockaddr) + 16, &Cb, (LPOVERLAPPED)op))
        {
                closesockets(op->c_socket); // 关闭客户端套接字
                op->c_socket = INVALID_SOCKET;
                PostQueuedCompletionStatus(hEvent_Server, 0, 0, (LPOVERLAPPED)op); // 发送完成状态
                delete[] op->buf;                                                                                                   // 释放缓冲区
                op->buf = NULL;
                delete op; // 删除结构体
                op = NULL;
                return 3; // 返回错误码 3
        }

        // 返回 0 表示成功
        return 0;
}

void Socket_Server_IO::ClientAccept(bool error, P_server_struct user_op)
{
        // 尝试在循环中接受新的客户端连接
        while (0 != Accept())
        {
                Sleep(1); // 等待一段短时间后重试
        }

        // 设置套接字选项以更新接受上下文
        setsockopt(user_op->c_socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&m_hSocket, sizeof(SOCKET));

        // 配置TCP keepalive设置
        DWORD Cb = 0;
        tcp_keepalive ka;
        ka.onoff = 1;                                         // 启用keepalive
        ka.keepalivetime = 1000 * 30;         // 30秒keepalive时间
        ka.keepaliveinterval = 1000 * 5; // 5秒keepalive间隔
        WSAIoctl(user_op->c_socket, SIO_KEEPALIVE_VALS, &ka, sizeof(ka), NULL, 0, &Cb, NULL, NULL);

        // 进入临界区以修改共享资源
        EnterCriticalSection(&m_token);
        m_count++; // 增加连接的客户端数量
        LeaveCriticalSection(&m_token);

        // 通知服务器函数新的连接
        onServerFunc(this, user_op->c_socket, tcp_server_connt, NULL, 0, m_count);

        // 如果在接受过程中出现错误,处理错误
        if (error)
        {
                EnterCriticalSection(&m_token);
                m_count--; // 减少连接的客户端数量
                LeaveCriticalSection(&m_token);

                // 通知服务器函数连接关闭
                onServerFunc(this, user_op->c_socket, tcp_server_close, NULL, 0, m_count);

                // 关闭客户端套接字并清理资源
                closesocket(user_op->c_socket);
                user_op->c_socket = INVALID_SOCKET;
                delete[] user_op->buf;
                user_op->buf = NULL;
                delete user_op;
                user_op = NULL;
                return;
        }

        // 设置状态为接收数据
        user_op->state = tcp_server_recv;

        WSABUF wsabuf;
        if (m_mate)
        {
                // 如果缓冲区大小已更新
                delete[] user_op->buf;                                                                // 删除原有的缓冲区
                user_op->bufOffset = 0;                                                                // 重置缓冲区偏移量
                user_op->buf = new char[sizeof(DWORD)];                                // 分配新缓冲区,大小为 DWORD 的字节大小
                user_op->bufSize = sizeof(DWORD);                                        // 设置缓冲区大小为 DWORD 的字节大小
                wsabuf.buf = user_op->buf + user_op->bufOffset;                // 设置 WSABUF 结构体的 buf 指针为缓冲区的起始位置
                wsabuf.len = user_op->bufSize - user_op->bufOffset; // 设置 WSABUF 结构体的 len 为缓冲区的剩余大小
        }
        else
        {
                // 使用现有缓冲区
                wsabuf.buf = user_op->buf; // 设置 WSABUF 结构体的 buf 指针为现有缓冲区的起始位置
                wsabuf.len = buf_len;           // 设置 WSABUF 结构体的 len 为现有缓冲区的长度
        }

        // 初始化标志和字节计数
        DWORD Flg = 0;
        Cb = 0;

        // 发出异步接收操作
        // 使用 WSARecv 函数进行异步接收操作
        if (WSARecv(user_op->c_socket, &wsabuf, 1, &Cb, &Flg, (LPWSAOVERLAPPED)user_op, NULL))
        {
                int ercode = WSAGetLastError(); // 获取错误代码

                if (ercode == WSAEFAULT)
                {
                        // 处理特定的错误情况(示例中未详细说明处理内容)
                        return; // 返回,可能需要根据具体情况进行特定处理
                }
                else if (ercode != WSA_IO_PENDING)
                {
                        // 处理一般错误情况

                        EnterCriticalSection(&m_token);
                        m_count--; // 减少连接的客户端数量
                        LeaveCriticalSection(&m_token);

                        // 通知服务器函数连接关闭
                        onServerFunc(this, user_op->c_socket, tcp_server_close, NULL, 0, m_count);

                        // 关闭客户端套接字并清理资源
                        closesocket(user_op->c_socket);                // 关闭客户端套接字
                        user_op->c_socket = INVALID_SOCKET; // 将套接字置为无效值
                        delete[] user_op->buf;                                // 删除缓冲区
                        user_op->buf = NULL;                                // 将缓冲区指针置空
                        delete user_op;                                                // 删除 user_op 对象
                        user_op = NULL;                                                // 将 user_op 指针置空
                        return;                                                                // 返回,结束处理
                }
        }
}

void Socket_Server_IO::RecvData(bool error, P_server_struct user_op)
{
        // 处理错误情况
        if (error)
        {
                // 进入临界区,减少连接的客户端数量
                EnterCriticalSection(&m_token);
                m_count--;                                                // 减少连接的客户端数量
                LeaveCriticalSection(&m_token); // 离开临界区

                // 通知服务器函数连接关闭
                onServerFunc(this, user_op->c_socket, tcp_server_close, 0, 0, m_count);

                // 清理资源
                delete[] user_op->buf; // 释放接收缓冲区
                user_op->buf = NULL;   // 将缓冲区指针置空
                delete user_op;                   // 释放用户操作结构体对象
                user_op = NULL;                   // 将结构体指针置空
                return;
        }

        // 检查是否启用缓冲区大小处理
        if (m_mate)
        {
                user_op->bufOffset += user_op->cb; // 更新已接收数据的偏移量

                // 如果缓冲区尚未完全接收,则继续接收
                if (user_op->bufOffset < user_op->bufSize)
                {
                        user_op->state = tcp_server_recv; // 设置状态为接收数据

                        WSABUF wsabuf;
                        // 设置 WSABUF 结构
                        if (m_mate)
                        {
                                wsabuf.buf = user_op->buf + user_op->bufOffset;                // 设置缓冲区起始位置
                                wsabuf.len = user_op->bufSize - user_op->bufOffset; // 设置剩余接收长度
                        }
                        else
                        {
                                wsabuf.buf = user_op->buf; // 设置缓冲区起始位置
                                wsabuf.len = buf_len;           // 设置缓冲区长度
                        }

                        DWORD Cb = 0;
                        DWORD Flg = 0;

                        // 发出异步接收操作
                        if (WSARecv(user_op->c_socket, &wsabuf, 1, &Cb, &Flg, (LPWSAOVERLAPPED)user_op, NULL))
                        {
                                int ercode = WSAGetLastError();

                                // 处理特定错误
                                if (ercode == WSAEFAULT)
                                {
                                        return; // 如果缓冲区不合法,直接返回
                                }
                                else if (ercode != WSA_IO_PENDING)
                                {
                                        EnterCriticalSection(&m_token); // 进入临界区
                                        m_count--;                                                // 减少连接的客户端数量
                                        LeaveCriticalSection(&m_token); // 离开临界区

                                        // 通知服务器函数连接关闭
                                        onServerFunc(this, user_op->c_socket, tcp_server_close, 0, 0, m_count);

                                        // 清理资源
                                        delete[] user_op->buf; // 释放接收缓冲区
                                        user_op->buf = NULL;   // 将缓冲区指针置空
                                        delete user_op;                   // 释放用户操作结构体对象
                                        user_op = NULL;                   // 将结构体指针置空
                                        return;
                                }
                        }
                        return;
                }

                // 处理接收到的数据大小
                DWORD size = *((DWORD *)(user_op->buf)); // 从缓冲区获取数据大小
                if (size > 65536000)
                {                                                                        // 检查数据大小是否过大
                        EnterCriticalSection(&m_token); // 进入临界区
                        m_count--;                                                // 减少连接的客户端数量
                        LeaveCriticalSection(&m_token); // 离开临界区

                        // 通知服务器函数连接关闭
                        onServerFunc(this, user_op->c_socket, tcp_server_close, 0, 0, m_count);

                        // 清理资源
                        delete[] user_op->buf; // 释放接收缓冲区
                        user_op->buf = NULL;   // 将缓冲区指针置空
                        delete user_op;                   // 释放用户操作结构体对象
                        user_op = NULL;                   // 将结构体指针置空
                        return;
                }

                // 如果缓冲区尚未完全接收,分配新的缓冲区并继续接收
                if (user_op->bufOffset < DWORD(sizeof(DWORD)) + size)
                {
                        delete[] user_op->buf;                                                   // 释放旧的接收缓冲区
                        user_op->buf = new char[sizeof(DWORD) + size]; // 分配新的接收缓冲区
                        user_op->bufSize = sizeof(DWORD) + size;           // 设置新缓冲区大小
                        user_op->bufOffset = sizeof(DWORD);                           // 设置偏移量从数据大小之后开始

                        memcpy(user_op->buf, &size, sizeof(DWORD)); // 将数据大小写入缓冲区

                        user_op->state = tcp_server_recv; // 设置状态为接收数据
                        WSABUF wsabuf;

                        // 设置 WSABUF 结构
                        if (m_mate)
                        {
                                wsabuf.buf = user_op->buf + user_op->bufOffset;                // 设置缓冲区起始位置
                                wsabuf.len = user_op->bufSize - user_op->bufOffset; // 设置剩余接收长度
                        }
                        else
                        {
                                wsabuf.buf = user_op->buf; // 设置缓冲区起始位置
                                wsabuf.len = buf_len;           // 设置缓冲区长度
                        }

                        DWORD Cb = 0;
                        DWORD Flg = 0;

                        // 发出异步接收操作
                        if (WSARecv(user_op->c_socket, &wsabuf, 1, &Cb, &Flg, (LPWSAOVERLAPPED)user_op, NULL))
                        {
                                int ercode = WSAGetLastError();

                                // 处理特定错误
                                if (ercode == WSAEFAULT)
                                {
                                        return; // 如果缓冲区不合法,直接返回
                                }
                                else if (ercode != WSA_IO_PENDING)
                                {
                                        EnterCriticalSection(&m_token); // 进入临界区
                                        m_count--;                                                // 减少连接的客户端数量
                                        LeaveCriticalSection(&m_token); // 离开临界区

                                        // 通知服务器函数连接关闭
                                        onServerFunc(this, user_op->c_socket, tcp_server_close, 0, 0, m_count);

                                        // 清理资源
                                        delete[] user_op->buf; // 释放接收缓冲区
                                        user_op->buf = NULL;   // 将缓冲区指针置空
                                        delete user_op;                   // 释放用户操作结构体对象
                                        user_op = NULL;                   // 将结构体指针置空
                                        return;
                                }
                        }
                        return;
                }

                // 如果接收到完整的数据,处理数据
                if (user_op->bufSize - sizeof(DWORD) > 0)
                {
                        // 调用处理接收数据的函数
                        onServerFunc(this, user_op->c_socket, tcp_server_recv, user_op->buf + sizeof(DWORD), user_op->bufSize - sizeof(DWORD), m_count);
                }

                // 释放接收缓冲区,为下一次接收操作分配新的缓冲区
                delete[] user_op->buf;
                user_op->buf = new char[sizeof(DWORD)];
                user_op->bufSize = sizeof(DWORD);
        }
        else
        {
                // 如果未启用缓冲区大小处理,直接处理接收到的数据
                onServerFunc(this, user_op->c_socket, tcp_server_recv, user_op->buf, user_op->cb, m_count);
        }

        // 重置缓冲区偏移量和状态,为下一次接收操作设置 WSABUF 结构
        user_op->bufOffset = 0;
        user_op->state = tcp_server_recv;
        WSABUF wsabuf;

        // 设置 WSABUF 结构用于下一次接收操作
        if (m_mate)
        {
                wsabuf.buf = user_op->buf + user_op->bufOffset;                // 设置缓冲区起始位置
                wsabuf.len = user_op->bufSize - user_op->bufOffset; // 设置剩余接收长度
        }
        else
        {
                wsabuf.buf = user_op->buf; // 设置缓冲区起始位置
                wsabuf.len = buf_len;           // 设置缓冲区长度
        }

        DWORD Cb = 0;
        DWORD Flg = 0;

        // 发出异步接收操作
        if (WSARecv(user_op->c_socket, &wsabuf, 1, &Cb, &Flg, (LPWSAOVERLAPPED)user_op, NULL))
        {
                int ercode = WSAGetLastError();

                // 处理特定错误
                if (ercode == WSAEFAULT)
                {
                        return; // 如果缓冲区不合法,直接返回
                }
                else if (ercode != WSA_IO_PENDING)
                {
                        EnterCriticalSection(&m_token); // 进入临界区
                        m_count--;                                                // 减少连接的客户端数量
                        LeaveCriticalSection(&m_token); // 离开临界区

                        // 通知服务器函数连接关闭
                        onServerFunc(this, user_op->c_socket, tcp_server_close, 0, 0, m_count);

                        // 清理资源
                        delete[] user_op->buf; // 释放接收缓冲区
                        user_op->buf = NULL;   // 将缓冲区指针置空
                        delete user_op;                   // 释放用户操作结构体对象
                        user_op = NULL;                   // 将结构体指针置空
                }
        }
}

int Socket_Server_IO::doSend(SOCKET so, char *buf, DWORD cb)
{
        // 检查要发送的数据大小是否超过最大允许大小
        if (cb > 65536000)
        {
                return 0; // 如果超过,返回0表示失败
        }

        // 分配并初始化一个新的 server_struct 实例用于发送操作
        server_struct *op = new server_struct;
        memset(op, 0, sizeof(server_struct));
        op->so = this;                                 // 将当前 Socket_Server_IO 实例指针赋值给 op 的 so 字段
        op->state = tcp_server_send; // 将状态设置为发送

        WSABUF wsabuf;

        // 检查是否启用了缓冲区大小处理
        if (m_mate)
        {
                // 分配一个新的缓冲区,包括数据大小
                op->buf = new char[sizeof(DWORD) + cb];
                op->bufSize = sizeof(DWORD) + cb;
                wsabuf.buf = op->buf;
                wsabuf.len = op->bufSize;

                // 将数据大小和实际数据复制到缓冲区中
                memcpy(wsabuf.buf, &cb, sizeof(DWORD));
                memcpy(wsabuf.buf + sizeof(DWORD), buf, cb);
        }
        else
        {
                // 如果未启用缓冲区大小处理,直接使用提供的缓冲区
                wsabuf.buf = buf;
                wsabuf.len = cb;
        }

        op->bufOffset = 0; // 初始化缓冲区偏移量

        // 发起一个异步发送操作
        if (WSASend(so, &wsabuf, 1, &op->cb, 0, (LPWSAOVERLAPPED)op, NULL))
        {
                int ercode = WSAGetLastError();
                // 处理特定错误
                if (ercode != WSA_IO_PENDING)
                {
                        // 如果发送操作失败,清理资源
                        delete[] op->buf;
                        op->buf = NULL;
                        delete op;
                        op = NULL;
                        return 1; // 返回1表示失败
                }
        }

        return 0; // 返回0表示发送操作成功启动
}

int Socket_Server_IO::doSend_sync(SOCKET so, char *buf, DWORD cb)
{
        if (cb > 65536000)
        {
                return 0;
        }
        if (m_mate)
        {
                memcpy(buf, &cb, sizeof(DWORD));
                memcpy(buf + sizeof(DWORD), buf, cb);
                if (send(so, buf, cb + sizeof(DWORD), 0))
                {
                        return 0;
                }
        }
        else
        {
                if (send(so, buf, cb, 0))
                {
                        return 0;
                }
        }
        return 1;
}
void Socket_Server_IO::OnSend(bool ercode, P_server_struct user_op)
{
        SOCKET n_so = user_op->c_socket;
        delete[] user_op->buf;
        user_op->buf = NULL;
        delete user_op;
        user_op = NULL;
        if (ercode)
        {
                closesockets(n_so);
                onServerFunc(this, n_so, tcp_server_stop, 0, 0, m_count);
                n_so = INVALID_SOCKET;
        }
}

class Socket_Client_IO;

typedef struct client_struct
{
        OVERLAPPED op;                                         // 用于重叠I/O操作的结构
        Socket_Client_IO *so;                         // 指向Socket_Client_IO实例的指针
        int state;                                                 // 客户端连接的状态
        char *buf;                                                 // 数据缓冲区
        DWORD slen;                                                 // 缓冲区的长度
        DWORD cb;                                                 // 传输的字节数
        DWORD bufSize;                                         // 缓冲区的大小
        DWORD bufOffset;                                 // 缓冲区的偏移量
} S_client_struct, *P_client_struct; // 结构体及其指针的类型定义

class Socket_Client_IO
{
public:
        Socket_Client_IO(void);
        ~Socket_Client_IO(void);
        int Init(char *host, unsigned short nPort, BOOL nIs, int time);
        void OnConnect(bool ercode, P_client_struct op);
        void OnClose(bool ercode, P_client_struct op);
        void OnRecv(bool ercode, P_client_struct op);
        int SoRecv(P_client_struct op);
        int Close();
        int doSend(char *buf, DWORD cb, int isok, char *outbuf, int outtime);
        void OnSend(bool ercode, P_client_struct op);
        SOCKET get_socket()
        {
                return m_hSocket;
        }

public:
        SOCKET m_hSocket;
        BOOL m_mate;
        int m_full;
        char *m_buf;
};

Socket_Client_IO::Socket_Client_IO(void)
{
        m_hSocket = INVALID_SOCKET;
}
Socket_Client_IO::~Socket_Client_IO(void)
{
        m_hSocket = INVALID_SOCKET;
}
int Socket_Client_IO::Init(char *host, unsigned short port, BOOL mate, int time)
{
        // 为客户端创建一个套接字
        m_hSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED);
        if (INVALID_SOCKET == m_hSocket)
        {
                return WSAGetLastError(); // 如果创建套接字失败,返回错误代码
        }

        // 将套接字与I/O完成端口关联
        HANDLE t = CreateIoCompletionPort((HANDLE)m_hSocket, hEvent_Client, 0, 0);
        if (NULL == t)
        {
                Close();                           // 如果关联失败,关闭套接字
                return GetLastError(); // 返回错误代码
        }

        // 初始化sockaddr_in结构以绑定套接字
        sockaddr_in in;
        in.sin_family = AF_INET;
        in.sin_addr.S_un.S_addr = 0; // 使用任何可用的本地地址
        in.sin_port = 0;                         // 使用任何可用的端口

        // 绑定套接字
        if (SOCKET_ERROR == bind(m_hSocket, (SOCKADDR *)&in, sizeof(in)))
        {
                Close();                                  // 如果绑定失败,关闭套接字
                return WSAGetLastError(); // 返回错误代码
        }

        m_mate = mate; // 存储mate参数

        // 解析主机地址并设置用于连接的sockaddr_in结构
        in.sin_family = AF_INET;
        struct hostent *pHost;
        pHost = gethostbyname(host);
        memcpy(&in.sin_addr.S_un.S_addr, pHost->h_addr_list[0], pHost->h_length);
        in.sin_addr.S_un.S_addr = inet_addr(inet_ntoa(in.sin_addr));
        in.sin_port = htons(port); // 设置端口

        // 将套接字设置为非阻塞模式
        unsigned long ul = 1;
        ioctlsocket(m_hSocket, FIONBIO, (unsigned long *)&ul);

        // 发起与服务器的连接
        connect(m_hSocket, (sockaddr *)&in, sizeof(sockaddr));

        // 设置连接的超时时间
        struct timeval timeout;
        fd_set r;
        FD_ZERO(&r);
        FD_SET(m_hSocket, &r);
        timeout.tv_sec = time;
        timeout.tv_usec = 0;

        // 使用select等待连接建立或超时
        int ret = select(m_hSocket, 0, &r, 0, &timeout);
        if (ret <= 0)
        {
                Close();  // 如果连接失败或超时,关闭套接字
                return 1; // 返回错误代码
        }

        // 为连接分配并初始化一个client_struct
        client_struct *op = new client_struct;
        memset(op, 0, sizeof(client_struct));
        op->so = this;
        op->state = tcp_client_connt; // 设置初始状态
        op->buf = NULL;
        op->bufSize = 0;
        op->bufOffset = 0;

        // 将完成状态发布到I/O完成端口
        PostQueuedCompletionStatus(hEvent_Client, 0, 0, (LPOVERLAPPED)op);

        return 0; // 返回成功
}
void Socket_Client_IO::OnConnect(bool ercode, P_client_struct op)
{
        // 设置套接字选项(这里的0x7010是一个自定义选项,具体含义取决于上下文)
        setsockopt(m_hSocket, SOL_SOCKET, 0x7010, NULL, 0);

        // 调用客户端连接函数,通知连接成功
        onClientFunc(this, m_hSocket, tcp_client_connt, NULL, 0);

        // 如果有错误码,关闭连接并返回
        if (ercode)
        {
                OnClose(ercode, op);
                return;
        }

        // 删除旧的缓冲区
        delete[] op->buf;

        // 根据m_mate的值分配新的缓冲区
        if (m_mate)
        {
                // 如果m_mate为true,分配sizeof(DWORD)大小的缓冲区
                op->buf = new char[sizeof(DWORD)];
                op->bufSize = sizeof(DWORD);
        }
        else
        {
                // 如果m_mate为false,分配tcp_len大小的缓冲区
                op->buf = new char[tcp_len];
                op->bufSize = tcp_len;
        }

        // 设置状态为接收数据
        op->state = tcp_client_recv;
        // 将缓冲区偏移量重置为0
        op->bufOffset = 0;

        // 尝试接收数据,如果接收失败,关闭连接并返回
        if (1 == SoRecv(op))
        {
                OnClose(ercode, op);
                return;
        }
}
void Socket_Client_IO::OnRecv(bool ercode, P_client_struct op)
{
        // 如果发生错误,关闭连接并返回
        if (ercode)
        {
                OnClose(ercode, op);
                return;
        }

        // 如果m_mate为true,进行以下操作
        if (m_mate)
        {
                // 更新缓冲区的偏移量
                op->bufOffset += op->cb;

                // 如果缓冲区未填满,继续接收数据
                if (op->bufOffset < op->bufSize)
                {
                        if (1 == SoRecv(op))
                        {
                                OnClose(ercode, op);
                                return;
                        }
                        return;
                }

                // 获取数据大小
                DWORD size = *((DWORD *)(op->buf));

                // 如果数据大小超过最大限制,关闭连接
                if (size > 65536000)
                {
                        OnClose(ercode, op);
                        return;
                }

                // 如果缓冲区未填满,重新分配缓冲区并继续接收数据
                if (op->bufOffset < DWORD(sizeof(DWORD)) + size)
                {
                        delete[] op->buf;
                        op->buf = new char[sizeof(DWORD) + size];
                        op->bufSize = sizeof(DWORD) + size;
                        op->bufOffset = sizeof(DWORD);
                        memcpy(op->buf, &size, sizeof(DWORD));
                        if (1 == SoRecv(op))
                        {
                                OnClose(ercode, op);
                                return;
                        }
                        return;
                }

                // 如果缓冲区内有数据,并且m_full大于0,复制数据到m_buf并重置m_full
                if (op->bufSize - sizeof(DWORD) > 0)
                {
                        if (m_full > 0)
                        {
                                memcpy(m_buf, op->buf + sizeof(DWORD), op->bufSize - sizeof(DWORD));
                                m_full = 0;
                        }

                        // 调用客户端接收函数
                        onClientFunc(this, m_hSocket, tcp_client_recv, op->buf + sizeof(DWORD), op->bufSize - sizeof(DWORD));
                }

                // 释放当前缓冲区并分配新的缓冲区
                delete[] op->buf;
                op->buf = new char[sizeof(DWORD)];
                op->bufSize = sizeof(DWORD);
        }
        else
        {
                // 如果m_mate为false,直接处理接收到的数据
                if (m_full > 0)
                {
                        memcpy(m_buf, op->buf, op->cb);
                }

                // 调用客户端接收函数
                onClientFunc(this, m_hSocket, tcp_client_recv, op->buf, op->cb);
                m_full = 0;
        }

        // 重置缓冲区偏移量
        op->bufOffset = 0;

        // 继续接收数据,如果失败则关闭连接
        if (1 == SoRecv(op))
        {
                OnClose(ercode, op);
                return;
        }
}

int Socket_Client_IO::SoRecv(P_client_struct op)
{
        // 设置当前Socket_Client_IO实例指针
        op->so = this;
        // 设置状态为接收数据
        op->state = tcp_client_recv;

        // 设置WSABUF结构,用于接收数据
        WSABUF wsabuf;
        wsabuf.buf = op->buf + op->bufOffset;          // 缓冲区的起始位置
        wsabuf.len = op->bufSize - op->bufOffset; // 缓冲区的长度

        // 设置标志为0
        DWORD Flg = 0;

        // 调用WSARecv函数异步接收数据
        if (WSARecv(m_hSocket, &wsabuf, 1, &op->cb, &Flg, (LPWSAOVERLAPPED)op, NULL))
        {
                // 如果WSARecv返回非零值,获取错误码
                int ercode = WSAGetLastError();

                // 如果错误码是WSAEFAULT,表示缓冲区不正确,返回0表示成功
                if (ercode == WSAEFAULT)
                {
                        return 0;
                }
                // 如果错误码不是WSA_IO_PENDING,表示接收操作没有挂起,返回1表示失败
                else if (ercode != WSA_IO_PENDING)
                {
                        return 1;
                }
        }

        // 返回0表示成功
        return 0;
}

void Socket_Client_IO::OnClose(bool ercode, P_client_struct op)
{
        delete[] op->buf;
        op->buf = NULL;
        delete op;
        op = NULL;
        onClientFunc(this, m_hSocket, tcp_client_stop, NULL, 0);
        Close();
}
int Socket_Client_IO::Close()
{
        closesockets(m_hSocket);
        m_hSocket = INVALID_SOCKET;
        return 0;
}
int Socket_Client_IO::doSend(char *buf, DWORD cb, int isok, char *outbuf, int outtime)
{
        // 检查发送数据大小是否超过限制
        if (cb > 65536000)
        {
                return 0; // 如果超过限制,返回0表示失败
        }

        // 设置成员变量m_full和m_buf
        m_full = isok;
        m_buf = outbuf;

        // 分配并初始化一个client_struct结构体
        client_struct *op = new client_struct;
        memset(op, 0, sizeof(client_struct));
        op->so = this;
        op->state = tcp_client_send;

        // 设置WSABUF结构,用于发送数据
        WSABUF wsabuf;

        // 如果m_mate为true,构造发送缓冲区
        if (m_mate)
        {
                op->buf = new char[sizeof(DWORD) + cb];
                op->bufSize = sizeof(DWORD) + cb;
                wsabuf.buf = op->buf;
                wsabuf.len = op->bufSize;
                memcpy(wsabuf.buf, &cb, sizeof(DWORD));                 // 复制数据大小
                memcpy(wsabuf.buf + sizeof(DWORD), buf, cb); // 复制实际数据
        }
        else
        {
                // 如果m_mate为false,直接使用传入的缓冲区
                op->buf = buf;
                op->bufSize = cb;
                wsabuf.buf = op->buf;
                wsabuf.len = op->bufSize;
        }

        // 调用WSASend函数异步发送数据
        if (WSASend(m_hSocket, &wsabuf, 1, &op->cb, 0, (LPWSAOVERLAPPED)op, NULL))
        {
                int ercode = WSAGetLastError();
                // 如果错误码不是WSA_IO_PENDING,表示发送操作失败
                if (ercode != WSA_IO_PENDING)
                {
                        delete[] op->buf; // 释放缓冲区
                        delete op;                  // 删除client_struct结构体
                        return 1;                  // 返回1表示失败
                }
        }

        int ni = 0;
        // 如果outtime小于等于0,将其设置为2秒
        if (outtime <= 0)
        {
                outtime = 2;
        }
        // 将outtime转换为毫秒
        outtime = outtime * 1000;

        // 等待发送完成或超时
        while (1 == m_full)
        {
                ni++;
                // 如果等待时间超过指定的超时时间,重置m_full和m_buf并退出循环
                if (ni > outtime)
                {
                        m_full = 0;
                        m_buf = NULL;
                        break;
                }
                Sleep(1); // 每次循环等待1毫秒
        }

        return 0; // 返回0表示成功
}

void Socket_Client_IO::OnSend(bool ercode, P_client_struct op)
{
        if (ercode)
        {
                OnClose(ercode, op);
                return;
        }
        if (m_mate)
        {
                delete[] op->buf;
                delete op;
        }
}

unsigned __stdcall Worker_server(void *pParam)
{
        while (true)
        {
                ULONG cb = 0;
                ULONG_PTR key = 0;
                server_struct *op = nullptr;
                bool error = false;

                if (!GetQueuedCompletionStatus(hEvent_Server, &cb, &key, (LPOVERLAPPED *)&op, INFINITE))
                {
                        error = true;
                }

                Socket_Server_IO *so = op->so;
                if (op->state == tcp_server_recv && cb <= 0)
                {
                        error = true;
                }

                op->cb = cb;

                if (so->m_stop)
                {
                        so->OnSend(true, op);
                        continue;
                }

                switch (op->state)
                {
                case tcp_server_connt:
                        so->ClientAccept(error, op);
                        break;
                case tcp_server_recv:
                        so->RecvData(error, op);
                        break;
                case tcp_server_send:
                        so->OnSend(error, op);
                        break;
                default:
                        // Handle unexpected state
                        break;
                }
        }

        _endthreadex(0);
        return 0;
}

// Client worker function
unsigned __stdcall Worker_client(void *pParam)
{
        while (true)
        {
                ULONG cb = 0;
                ULONG_PTR key = 0;
                client_struct *op = nullptr;
                bool error = false;

                if (!GetQueuedCompletionStatus(hEvent_Client, &cb, &key, (LPOVERLAPPED *)&op, INFINITE))
                {
                        error = true;
                }

                Socket_Client_IO *so = op->so;
                if (op->state == tcp_client_recv && cb <= 0)
                {
                        error = true;
                }

                op->cb = cb;

                switch (op->state)
                {
                case tcp_client_connt:
                        so->OnConnect(error, op);
                        break;
                case tcp_client_recv:
                        so->OnRecv(error, op);
                        break;
                case tcp_client_send:
                        so->OnSend(error, op);
                        break;
                default:
                        // Handle unexpected state
                        break;
                }
        }

        _endthreadex(0);
        return 0;
}

extern "C" __declspec(dllexport) int __stdcall socket_init(onServer_ex nFun, onClient_ex cFun)
{
        WSAData wsa;
        if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
        {
                return WSAGetLastError();
        }

        onServerFunc = nFun;
        onClientFunc = cFun;

        hEvent_Server = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
        if (hEvent_Server == NULL)
        {
                return GetLastError();
        }

        hEvent_Client = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
        if (hEvent_Client == NULL)
        {
                CloseHandle(hEvent_Server);
                return GetLastError();
        }

        SYSTEM_INFO info;
        GetSystemInfo(&info);
        g_cpu = info.dwNumberOfProcessors + 2;
        if (g_cpu < 5)
        {
                g_cpu = 5;
        }

        for (int i = 0; i < g_cpu; i++)
        {
                HANDLE threadHandle = (HANDLE)_beginthreadex(NULL, 0, &Worker_server, NULL, 0, NULL);
                if (threadHandle != NULL)
                {
                        CloseHandle(threadHandle);
                }

                threadHandle = (HANDLE)_beginthreadex(NULL, 0, &Worker_client, NULL, 0, NULL);
                if (threadHandle != NULL)
                {
                        CloseHandle(threadHandle);
                }
        }

        return 0;
}

extern "C" __declspec(dllexport) int __stdcall socket_server(char *host, unsigned short nPort, int nIs)
{
        Socket_Server_IO *dServer = new Socket_Server_IO;
        if (0 != dServer->Init(host, nPort, nIs))
        {
                delete dServer;
                dServer = NULL;
                return 0;
        }
        return 0;
        // 编译的时候需要注释上面返回 并且返回真实指针地址
        // return (int)dServer;
}
extern "C" __declspec(dllexport) int __stdcall socket_server_send(HANDLE so, SOCKET client_so, char *buf, int len)
{
        return ((Socket_Server_IO *)so)->doSend(client_so, buf, len);
}
extern "C" __declspec(dllexport) int __stdcall socket_server_sends(HANDLE so, SOCKET client_so, char *buf, int len)
{
        return ((Socket_Server_IO *)so)->doSend_sync(client_so, buf, len);
}
extern "C" __declspec(dllexport) int __stdcall socket_server_get_port(HANDLE so)
{
        return ((Socket_Server_IO *)so)->get_port();
}
char *__stdcall socket_server_get_ip(HANDLE so, SOCKET client_so)
{
        return ((Socket_Server_IO *)so)->get_ip(client_so);
}
SOCKET __stdcall socket_server_get_socket(HANDLE so)
{
        return ((Socket_Server_IO *)so)->get_socket();
}
extern "C" __declspec(dllexport) int __stdcall socket_server_close(SOCKET so)
{
        return closesockets(so);
}

extern "C" __declspec(dllexport) int __stdcall socket_server_stop(HANDLE so)
{
        if (IsBadReadPtr(so, 4) != 0)
        {
                return 0;
        }
        Socket_Server_IO *dServer = ((Socket_Server_IO *)so);
        dServer->Close();
        delete dServer;
        dServer = NULL;
        return 0;
}

extern "C" __declspec(dllexport) int __stdcall socket_client(char *host, unsigned short nPort, BOOL nIs, int time)
{
        Socket_Client_IO *dClient = new Socket_Client_IO;
        if (0 != dClient->Init(host, nPort, nIs, time))
        {
                delete dClient;
                dClient = NULL;
                return 0;
        }
        return 0;
        // 编译的时候需要注释上面返回 并且返回真实指针地址
        // return (int)dClient;
}
extern "C" __declspec(dllexport) int __stdcall socket_client_send(HANDLE so, char *buf, int len, int isok, char *outbuf, int outtime)
{
        return ((Socket_Client_IO *)so)->doSend(buf, len, isok, outbuf, outtime);
}

extern "C" __declspec(dllexport) int __stdcall socket_client_close(HANDLE so)
{
        return ((Socket_Client_IO *)so)->Close();
}

extern "C" __declspec(dllexport) int __stdcall socket_client_get(HANDLE so)
{
        return ((Socket_Client_IO *)so)->get_socket();
}

void __stdcall ServerCallback(HANDLE Server, SOCKET so, int type, char *buf, int len, int count)
{

        if (type == 1)
        {
                printf("ServerCallback  Connect \n");
                char sendData[] = "ServerCallback:helloworld";
                socket_server_send(Server, so, sendData, strlen(sendData));
        }
        else if (type == 2)
        {
                printf("Received data: %.*s\n", len, buf);
        }
}

void __stdcall ClientCallback(HANDLE Client, SOCKET so, int type, char *buf, int len)
{

        if (type == 1)
        {
                printf("ClientCallback  Connect \n");
                char sendData[] = "ClientCallback:helloworld";
                socket_client_send(Client, sendData, strlen(sendData), 0, 0, 0);
        }
        if (type == 2)
        {
                printf("Received data: %.*s\n", len, buf);
        }
}

int __stdcall main()
{
        if (socket_init(ServerCallback, ClientCallback) == 0)
        {
                Socket_Server_IO *s = new Socket_Server_IO;
                printf("S %d \n", s->Init((char *)"0.0.0.0", 8800, 0));
                Socket_Client_IO *c = new Socket_Client_IO;
                printf("C %d \n", c->Init((char *)"127.0.0.1", 8800, 0, 30));
                Sleep(1000 * 60 * 60 * 30);
        }
        return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
                break;
        }
        return TRUE;
}

WinSocket.rar

247.12 KB, 下载次数: 53, 下载积分: 精币 -2 枚

评分

参与人数 5好评 +3 精币 +6 收起 理由
qq1004043585 + 1 YYDS~!
文西哥 + 1 支持开源~!感谢分享
財財 + 1 感谢分享,很给力!~
baitso + 1 + 2 支持开源~!感谢分享
Crb + 1 + 2 老哥有C++ 调用例子吗

查看全部评分


头像被屏蔽
结帖率:100% (4/4)
 楼主| 发表于 2024-7-1 16:26:30 | 显示全部楼层   安徽省合肥市
对于ETCP的代码总结 从封装给易语言角度来说,ETCP确实设计很棒,
充分弥补了易语言天生的残疾,
但从C++角度来说,
ETCP代码算不上完美,
而且还有一点低级bug 但是bug的又不明显 应为没到影响运行
因为VS太过于庞大了,所以直接略过VS环境,采用轻量级的mingw编译
一个记事本就可以改动代码 一行命令就可以编译
下一级重点讲解一下 ETCP 服务端的实现
其实不难看出 初始化时候创建了个IOCP 线程池
然后通过IO重叠 实现整个的 Scoket交互
虽然ETCP作者曾经说用的是环形缓存 说白了就是一个 字节指针 相当于易语言的程序集变量
虽然没有什么很高级的东西  但是 该有的都有了

点评

修正一下 类成员变量(程序集变量)   安徽省合肥市  发表于 2024-7-1 16:29
回复 支持 反对

使用道具 举报

发表于 2024-7-16 07:53:40 | 显示全部楼层   安徽省合肥市
支持开源~!感谢分享
回复 支持 反对

使用道具 举报

结帖率:33% (1/3)
发表于 2024-7-13 21:24:44 | 显示全部楼层   广东省深圳市
支持开源~!感谢分享
回复 支持 反对

使用道具 举报

头像被屏蔽
结帖率:100% (4/4)
 楼主| 发表于 2024-7-7 21:02:06 | 显示全部楼层   安徽省合肥市

等完善了 再弄这块
回复 支持 反对

使用道具 举报

头像被屏蔽
结帖率:100% (4/4)
 楼主| 发表于 2024-7-7 21:01:32 | 显示全部楼层   安徽省合肥市
四叶草接单 发表于 2024-7-7 11:09
这样的话真是太棒了!用原生易语言封装的话,替换易语言自带的到时就很好用了。希望tcp能加上ssl认证功能 ...

这块估计还挺漫长的 因为要先保证稳定高效 至于新加功能 暂时还未考虑 虽然有想过SSL 但是日后可能是辅助SSL 这种
回复 支持 反对

使用道具 举报

结帖率:77% (55/71)

签到天数: 27 天

发表于 2024-7-7 20:59:06 | 显示全部楼层   湖北省武汉市
老大弄个qq群.....
回复 支持 反对

使用道具 举报

结帖率:100% (3/3)

签到天数: 29 天

发表于 2024-7-7 11:09:45 | 显示全部楼层   广东省阳江市
盖伦总管 发表于 2024-7-5 22:53
正在做,不过方向类似HP_SOCKET 4.14 主要是用于替换易语言自带的客户Duan服务端端组件 和互联网远程支持 ...

这样的话真是太棒了!用原生易语言封装的话,替换易语言自带的到时就很好用了。希望tcp能加上ssl认证功能,但是不希望用openssl,它太大了。既然是主打轻易级,ssl认证建议封装SSPI的api,这样就相当于一个轻量级的hp了。如果需要帮助的话,可以联系我或者发上论坛一起帮忙封装,我之前也做过这部分的工作,后面比较忙就没继续了
回复 支持 反对

使用道具 举报

头像被屏蔽
结帖率:100% (4/4)
 楼主| 发表于 2024-7-5 22:53:24 | 显示全部楼层   安徽省合肥市
qq1004043585 发表于 2024-7-4 02:59
期待盖伦老哥弄个新的ETCP

等后续更新下
回复 支持 反对

使用道具 举报

头像被屏蔽
结帖率:100% (4/4)
 楼主| 发表于 2024-7-5 22:53:04 | 显示全部楼层   安徽省合肥市
四叶草接单 发表于 2024-7-4 00:04
老哥,感谢你修复etcp,etcp是一个很轻易的tcp模块,很好用。另外,既然是想用在易语言上,为什么不直接把w ...

正在做,不过方向类似HP_SOCKET 4.14 主要是用于替换易语言自带的客户Duan服务端端组件 和互联网远程支持库    目前代码正在处于重写状态 完成度只有40%左右  
回复 支持 反对

使用道具 举报

签到天数: 27 天

发表于 2024-7-5 09:40:03 | 显示全部楼层   浙江省宁波市
感谢分享,支持开源!!!
回复 支持 反对

使用道具 举报

签到天数: 5 天

发表于 2024-7-4 20:36:36 | 显示全部楼层   福建省福州市
感谢分享
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表