TCP-完成端口

#pragma once
#define _WINSOCK_DEPRECATED_NO_WARNINGS
//#define FD_SETSIZE 1024
	

#include <winsock2.h>
#include <windows.h>
#include <string>
#include <mswsock.h>
#include <iostream>

#pragma comment(lib,"Mswsock.lib")
#pragma comment(lib,"ws2_32.lib")

using namespace std;

//自定义的消息值不能和系统消息冲突
#define WSAAsyncSelectMsg    WM_USER +1

#define Sever_Port 9999



struct fd_es_set //事件模型
{
    UINT count;
    SOCKET sockall[1024];
    HANDLE eventall[1024];
};


struct fd_win_set//消息模型
{
    UINT count;
    SOCKET sockall[1024];
};


struct fd_esIo_set //重叠IO事件模型
{
    UINT count;
    SOCKET sockall[1024];
    OVERLAPPED IOeventall[1024];
};


struct fd_FinshIo_set //完成端口模型
{
    UINT count;
    SOCKET sockall[1024];
    OVERLAPPED IOeventall[1024];
    HANDLE Port;      //完成端口
    PHANDLE Pthread;  //保存的线程指针
    DWORD ThreadNum;  //系统的线程数量
    BOOL  ThreadOpen; //线程开关
};
#include "main.h"
#define  WSA_MAX_STR 1024

bool PostRecv(UINT Index);
bool PostSend(UINT Index, string sendmsg);
bool PostAccept();

fd_FinshIo_set allsock;

char _recvstr[WSA_MAX_STR]; //recv消息用的



VOID Server_write_error()
{

}

void clear()
{
    //释放线程句柄

    for (UINT i = 0; i < allsock.ThreadNum; i++)
    {
        CloseHandle(allsock.Pthread[i]);
    }

    //释放内存
    free(allsock.Pthread);


    /*释放整个结构体,可能有些事件和socket已经被释放过了,不影响*/
    for (UINT i = 0; i < allsock.count; i++)
    {
        if (0 == allsock.sockall[i])
            continue;

        //释放stocket
        closesocket(allsock.sockall[i]);
        //关闭事件对象
        WSACloseEvent(allsock.IOeventall[i].hEvent);
    }

    //清理网络库
    WSACleanup();
}


//线程用于接收回调
DWORD WINAPI PTHREAD_ROUTINE(LPVOID lpThreadParameter)
{
    _Out_ DWORD lpNumberOfBytes;        //字节数
    _Out_ ULONG_PTR lpCompletionKey;    //绑定函数CreateIoCompletionPort传来的参数3
    _Out_ LPOVERLAPPED lpOverlapped;   //重叠结构
    //取通知信息,无信息会自动挂起线程
    while (allsock.ThreadOpen)
    {// 参数3是传入参数,发给函数GetQueuedCompletionStatus的参数3
        bool ret = GetQueuedCompletionStatus(allsock.Port, &lpNumberOfBytes, &lpCompletionKey, &lpOverlapped, INFINITE);

        //if (false == ret)
        //{
        //    printf("error_GetQueuedCompletionStatus\n");
        //    continue;
        //}

        if (0 == lpCompletionKey)
        {//0是服务器的数组下标,服务器链接
            //绑定完成端口
                //绑定sorket 和 完成端口  参数3是传入参数,发给函数GetQueuedCompletionStatus的参数3
            if (0 == CreateIoCompletionPort((HANDLE)allsock.sockall[allsock.count], allsock.Port, allsock.count, 0))
            {
                printf("error");
                //关闭客户端链接
                closesocket(allsock.sockall[allsock.count]);
                WSACloseEvent(allsock.IOeventall[allsock.count].hEvent);
            }

            /*接收客户端的连接消息*/
            PostRecv(allsock.count);
            /*返回给服务器消息*/
            string sedmsg = "服务器已链接";
            PostSend(allsock.count, sedmsg);

            allsock.count++;

            /*重新投递accept*/
            PostAccept();
        }
        else
        {//客户端消息
            if (0 != _recvstr[0])
            {//recv
                printf("recv:%s\n", _recvstr);
                memset(_recvstr, 0, sizeof(_recvstr));

                string sedmsg = "服务器收到";
                PostSend(lpCompletionKey, sedmsg);

                //继续传递
                PostRecv(lpCompletionKey);
            }
            else
            {//send
                //printf("sendok\n");
                //PostSend(lpCompletionKey);
            }

            //客户端关闭
            if (0 == lpNumberOfBytes)
            {
                printf("close\n");
                //关闭socket 和事件
                closesocket(allsock.sockall[lpCompletionKey]);
                WSACloseEvent(allsock.IOeventall[lpCompletionKey].hEvent);

                //从数组清空 ,由于完成端口和下标指定了,所以不能用之前的方法
                allsock.sockall[lpCompletionKey] = 0;
                allsock.IOeventall[lpCompletionKey].hEvent = 0;

            }

        }

}

   return 1;
}




bool PostSend(UINT Index, string sendmsg)
{
    WSABUF lpBuffers = { (ULONG)sendmsg.length() ,(char*)sendmsg.c_str() };
    DWORD lpNumberOfBytesRecvd;
    DWORD  flag = 0;

    int ret = WSASend(allsock.sockall[Index],  //接受的客户端socket
        &lpBuffers,       //接收的缓冲区
        1,      //参数二的个数
        &lpNumberOfBytesRecvd,      //接收成功的话保存接收字节数量
        flag,                            //设置flag,默认0
        &allsock.IOeventall[Index],        //IO重叠结构
        0                                //IO重叠回调例程
    );


    int error = WSAGetLastError();
    if (ERROR_IO_PENDING != error)
    {//函数执行出错
        return 0;
    }
    return 1;
}





bool PostRecv(UINT Index)
{

    WSABUF lpBuffers = { sizeof(_recvstr) ,_recvstr };
    DWORD lpNumberOfBytesRecvd;
    DWORD  flag = 0;

    int ret = WSARecv(allsock.sockall[Index],  //接受的客户端socket
        &lpBuffers,       //接收的缓冲区
        1,      //参数二的个数
        &lpNumberOfBytesRecvd,      //接收成功的话保存接收字节数量
        &flag,                            //recv参数5,默认0
        &allsock.IOeventall[Index],        //IO重叠结构
        0                                //IO重叠回调例程
    );

    int error = WSAGetLastError();
    if (ERROR_IO_PENDING != error)
    {//函数执行出错
        return 0;
    }
    return 1;
}




bool PostAccept()
{
    /*创建socket和event,给客户端Socket和event加入数组*/
    allsock.sockall[allsock.count] = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED);
    allsock.IOeventall[allsock.count].hEvent = WSACreateEvent();


    char getstr[WSA_MAX_STR];
    DWORD lpdwBytesReceived;
    /*返回true代表客户端立即连上了服务器*/
    bool res = AcceptEx(allsock.sockall[0],     //投递参数1服务器socket,
        allsock.sockall[allsock.count], //   异步接收服务器socket
        getstr,//缓冲区制作,接收新链接发送的第一条数据,之后数据用WSArecv接收了,鸡肋
        0,  //设置0 参数3无效了;
        sizeof(sockaddr_in) + 16,//为本地地址信息保留的字节数,此值至少比传输协议大16字节
        sizeof(sockaddr_in) + 16,//为客户端地址信息保留的字节数,此值至少比传输协议大16字节
        &lpdwBytesReceived,              //接受参数3数据的长度         
        &allsock.IOeventall[0]          //服务器的重叠结构
    );

    int error = WSAGetLastError();
    if (ERROR_IO_PENDING != error)
    {//函数执行出错
        return 0;
    }
    return 1;
}






/*1.打开网络库
* 2.校验网络库版本
* 3.创建SOCKET
* 4.绑定IP地址和端口
* 5.创建完成端口,并绑定客户端socket/和完成端口
* 6.开始监听
* 7.开始异步接收accept recv
*/
int create()
{
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;

    /* 使用Windef.h中声明的MAKEWORD(低字节、高字节)宏 */
    wVersionRequested = MAKEWORD(2, 2);

    /*启用网络链接库,调用的封装库命令*/
    err = WSAStartup(wVersionRequested, &wsaData);
    if (err != 0) {
        /* Tell the user that we could not find a usable */
        /* Winsock DLL.                                  */
        printf("WSAStartup failed with error: %d\n", err);
        return -1;
    }

    /*确认WinSock DLL支持2.2*/

    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
        /* Tell the user that we could not find a usable */
        /* WinSock DLL.                                  */
        printf("Could not find a usable version of Winsock.dll\n");
        //清理网络库
        WSACleanup();
        return -1;
    }


    //创建套接字。 创建网络类型 tcp或者upd
   //SOCKET socketServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    SOCKET socketServer = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED);

    if (INVALID_SOCKET == socketServer)
    {
        string ret = to_string(WSAGetLastError());
        MessageBoxA(0, "error_socket", ret.c_str(), 0);
        //清理网络库
        WSACleanup();
        return -1;
    }
    //设置sockaddr结构
    sockaddr_in saServer;
    saServer.sin_family = AF_INET;
    saServer.sin_addr.s_addr = INADDR_ANY;
    saServer.sin_port = htons(Sever_Port);



    // 绑定本机(服务器)IP和端口
    //sockaddr结构中的信息
    if (SOCKET_ERROR == bind(socketServer, (SOCKADDR*)&saServer, sizeof(saServer)))
    {
        string ret = to_string(WSAGetLastError());
        MessageBoxA(0, "error_bind", ret.c_str(), 0);
        //释放stocket
        closesocket(socketServer);
        //清理网络库
        WSACleanup();
        return -1;
    }

    /*将服务器socket和事件对象句柄写进结构体*/
    allsock.IOeventall[allsock.count].hEvent = WSACreateEvent();;
    allsock.sockall[allsock.count] = socketServer;
    allsock.count++;


    //创建一个完成端口
    allsock.Port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
    if ( 0 == allsock.Port)
    {
        string ret = to_string(WSAGetLastError());
        MessageBoxA(0, "error_listen", ret.c_str(), 0);
        //释放stocket
        closesocket(socketServer);
        //清理网络库
        WSACleanup();
        return -1;
    }
    //绑定sorket 和 完成端口  参数3是传入参数,发给函数GetQueuedCompletionStatus的参数3
    if (0 == CreateIoCompletionPort((HANDLE)socketServer, allsock.Port, 0, 0))
    {
        string ret = to_string(WSAGetLastError());
        MessageBoxA(0, "error_listen", ret.c_str(), 0);

        CloseHandle(allsock.Port);
        //释放stocket
        closesocket(socketServer);
        //清理网络库
        WSACleanup();
        return -1;
   }




    /*监听本机(服务器)的套接字*/

    if (SOCKET_ERROR == listen(socketServer, SOMAXCONN))
    {
        string ret = to_string(WSAGetLastError());
        MessageBoxA(0, "error_listen", ret.c_str(), 0);
        CloseHandle(allsock.Port);
        //释放stocket
        closesocket(socketServer);
        //清理网络库
        WSACleanup();
        return -1;
    }

    //创建线程,查询CPU是几核就创建几核
    SYSTEM_INFO lpSystemInfo;
    GetSystemInfo(&lpSystemInfo);
    allsock.ThreadNum = lpSystemInfo.dwNumberOfProcessors;
    allsock.Pthread = (PHANDLE)malloc(allsock.ThreadNum  * sizeof(HANDLE));
    allsock.ThreadOpen = true;

    /*创建线程来用于消息接收*/
    for (UINT i = 0; i < allsock.ThreadNum; i++)
    {
        allsock.Pthread[i] = CreateThread(0, 0, PTHREAD_ROUTINE, 0, 0, 0);
    }



    异步接收客户端
    if (0 == PostAccept())
    {
        clear();
    
        return 0;
    }



    while (allsock.ThreadOpen)
    {
        Sleep(1000);
    }

    return 1;
}


BOOL  WINAPI HANDLER_ROUTINE(_In_ DWORD CtrlType)
{
    switch (CtrlType)
    {
    case CTRL_CLOSE_EVENT:
    {
        allsock.ThreadOpen = false;
        clear();
    }
    default:
        break;
    }

    return true;
}



int main()
{

    //创建个回调监视控制台关闭
    SetConsoleCtrlHandler(HANDLER_ROUTINE,true);
    create();

    //  create("127.0.0.1");


    return 0;
}

上面有数组内存的问题,下面是完美方案

#pragma once
#define _WINSOCK_DEPRECATED_NO_WARNINGS
//#define FD_SETSIZE 1024
	

#include <winsock2.h>
#include <windows.h>
#include <string>
#include <mswsock.h>
#include <iostream>
#include <vector>

#pragma comment(lib,"Mswsock.lib")
#pragma comment(lib,"ws2_32.lib")

using namespace std;

//自定义的消息值不能和系统消息冲突
#define WSAAsyncSelectMsg    WM_USER +1

#define Sever_Port 12345



struct fd_es_set //事件模型
{
    UINT count;
    SOCKET sockall[1024];
    HANDLE eventall[1024];
};


struct fd_win_set//消息模型
{
    UINT count;
    SOCKET sockall[1024];
};


struct fd_esIo_set //重叠IO事件模型
{
    UINT count;
    SOCKET sockall[1024];
    OVERLAPPED IOeventall[1024];
};


enum class Socket_type
{
    Socket_APPECT,
    Socket_SEND,
    Socket_RECV,
    Socket_CONNET,
    Socket_CLOSE
};

#define  WSA_MAX_STR 1024

//接收和保存客户端信息
typedef class OnlineClientMsg
{
public:
    OVERLAPPED lpOverlapped;   //重叠结构
    SOCKET sockall;
    Socket_type TYPE;
    char _recvstr[WSA_MAX_STR]; //recv消息用的

}ClientMsg;



class set_system
{
public:
    HANDLE Port;      //完成端口
    PHANDLE Pthread;  //保存的线程指针
    DWORD ThreadNum;  //系统的线程数量
    BOOL  ThreadOpen; //线程开关
   SOCKET Seversockall;
};
#include "main.h"

bool PostRecv(OnlineClientMsg* msg);
 bool PostSend(OnlineClientMsg* msg, string sendmsg);
bool PostAccept();

set_system set;





VOID Server_write_error()
{

}

void clear()
{
    //释放线程句柄

    for (UINT i = 0; i < set.ThreadNum; i++)
    {
        CloseHandle(set.Pthread[i]);
    }

    //释放内存
    free(set.Pthread);


    //释放stocket
    closesocket(set.Seversockall);

    //清理网络库
    WSACleanup();
}


//线程用于接收回调
DWORD WINAPI PTHREAD_ROUTINE(LPVOID lpThreadParameter)
{
    _Out_ DWORD lpNumberOfBytes;        //字节数
    _Out_ ULONG_PTR lpCompletionKey;    //绑定函数CreateIoCompletionPort传来的参数3
    _Out_ OnlineClientMsg*  NewclientMsg ; //用自己的结构体替代LPOVERLAPPED,这样能接收到更多数据


    //取通知信息,无信息会自动挂起线程
    while (set.ThreadOpen)
    {// 参数3是传入参数,发给函数GetQueuedCompletionStatus的参数3
        bool ret = GetQueuedCompletionStatus(set.Port, &lpNumberOfBytes, &lpCompletionKey, (LPOVERLAPPED*)&NewclientMsg, INFINITE);

        if (false == ret)
        {
            printf("Socket_CLOSE\n");
            closesocket(NewclientMsg->sockall);
            delete  NewclientMsg;
            continue;
        }
       

        {
            //绑定完成端口       
            switch (NewclientMsg->TYPE)
            {//接收到连接请求
            case Socket_type::Socket_APPECT: 
            {       
                //绑定sorket 和 完成端口  参数3是传入参数,发给函数GetQueuedCompletionStatus的参数3
                if (0 == CreateIoCompletionPort((HANDLE)NewclientMsg->sockall, set.Port, 1, 0))
                {
                    printf("error  CreateIoCompletionPort");
                    //关闭客户端链接
                    closesocket(NewclientMsg->sockall);
                    // WSACloseEvent(allsock.IOeventall[allsock.count].hEvent);
                    delete  NewclientMsg;
                }


                  /*接收到请求链接后给客户端发送个 通信成功的消息*/
                PostSend(NewclientMsg , "OK");


                /*重新投递accept*/
                PostAccept();   

                break;
            }
            case Socket_type::Socket_RECV:
            {
                {
                   // printf("recv:%s\n ", NewclientMsg->_recvstr);
                    cout <<"recv:" << NewclientMsg->_recvstr << endl;
                    /*返回给服务器消息*/
           
                    string sedmsg = "服务器收到";
                    PostSend(NewclientMsg, sedmsg);
               }
  

                break;
            }
            case Socket_type::Socket_SEND:
            {
                //投递接收这个客户端消息的线程
                PostRecv(NewclientMsg);
    
                break;
            }
            default:
                break;
            }





        }

}

   return 1;
}




bool PostSend(OnlineClientMsg* msg,string sendmsg)
{
    msg->TYPE = Socket_type::Socket_SEND;

    WSABUF lpBuffers = { (ULONG)sendmsg.length() ,(char*)sendmsg.c_str() };
    DWORD lpNumberOfBytesRecvd;
    DWORD  flag = 0;

    int ret = WSASend(msg->sockall,  //接受的客户端socket
        &lpBuffers,       //接收的缓冲区
        1,      //参数二的个数
        &lpNumberOfBytesRecvd,      //接收成功的话保存接收字节数量
        flag,                            //设置flag,默认0
        &msg->lpOverlapped,        //IO重叠结构
        0                                //IO重叠回调例程
    );


    int error = WSAGetLastError();
    if (ERROR_IO_PENDING != error)
    {//函数执行出错
        return 0;
    }
    return 1;
}





bool PostRecv(OnlineClientMsg* msg)
{
    msg->TYPE = Socket_type::Socket_RECV;
    ZeroMemory(&msg->_recvstr, sizeof(msg->_recvstr));

    WSABUF lpBuffers = { sizeof(msg->_recvstr) ,  msg->_recvstr };
    DWORD lpNumberOfBytesRecvd;
    DWORD  flag = 0;

    int ret = WSARecv(msg->sockall,  //接受的客户端socket
        &lpBuffers,       //接收的缓冲区
        1,      //参数二的个数
        &lpNumberOfBytesRecvd,      //接收成功的话保存接收字节数量
        &flag,                            //recv参数5,默认0
        &msg->lpOverlapped,        //IO重叠结构
        0                                //IO重叠回调例程
    );

    int error = WSAGetLastError();
    if (ERROR_IO_PENDING != error)
    {//函数执行出错
        return 0;
    }
    return 1;
}




bool PostAccept()
{
    ClientMsg* msg = new ClientMsg;
    if (msg)
        ZeroMemory(msg,sizeof(ClientMsg));


    msg->TYPE = Socket_type::Socket_APPECT;
    msg->sockall = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED);


    char getstr[WSA_MAX_STR];
    DWORD lpdwBytesReceived;
    /*返回true代表客户端立即连上了服务器*/
    bool res = AcceptEx(set.Seversockall,     //投递参数1服务器socket,
        msg->sockall, //   异步接收客户端socket
        getstr,//缓冲区制作,接收新链接发送的第一条数据,之后数据用WSArecv接收了,鸡肋
        0,  //设置0 参数3无效了;
        sizeof(sockaddr_in) + 16,//为本地地址信息保留的字节数,此值至少比传输协议大16字节
        sizeof(sockaddr_in) + 16,//为客户端地址信息保留的字节数,此值至少比传输协议大16字节
        &lpdwBytesReceived,              //接受参数3数据的长度         
       (LPOVERLAPPED)msg       //重叠结构 跟着参数2 socket一起传入GetQueuedCompletionStatus
    );

    int error = WSAGetLastError();
    if (ERROR_IO_PENDING != error)
    {//函数执行出错
        return 0;
    }
    return 1;
}






/*1.打开网络库
* 2.校验网络库版本
* 3.创建SOCKET
* 4.绑定IP地址和端口
* 5.创建完成端口,并绑定客户端socket/和完成端口
* 6.开始监听
* 7.开始异步接收accept recv
*/
int create()
{
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;

    /* 使用Windef.h中声明的MAKEWORD(低字节、高字节)宏 */
    wVersionRequested = MAKEWORD(2, 2);

    /*启用网络链接库,调用的封装库命令*/
    err = WSAStartup(wVersionRequested, &wsaData);
    if (err != 0) {
        /* Tell the user that we could not find a usable */
        /* Winsock DLL.                                  */
        printf("WSAStartup failed with error: %d\n", err);
        return -1;
    }

    /*确认WinSock DLL支持2.2*/

    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
        /* Tell the user that we could not find a usable */
        /* WinSock DLL.                                  */
        printf("Could not find a usable version of Winsock.dll\n");
        //清理网络库
        WSACleanup();
        return -1;
    }


    //创建套接字。 创建网络类型 tcp或者upd
   //SOCKET socketServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    SOCKET socketServer = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED);

    if (INVALID_SOCKET == socketServer)
    {
        string ret = to_string(WSAGetLastError());
        MessageBoxA(0, "error_socket", ret.c_str(), 0);
        //清理网络库
        WSACleanup();
        return -1;
    }

    set.Seversockall = socketServer;

    //设置sockaddr结构
    sockaddr_in saServer;
    saServer.sin_family = AF_INET;
    saServer.sin_addr.s_addr =  INADDR_ANY;//inet_addr("192.168.31.55");
    saServer.sin_port = htons(Sever_Port);



    // 绑定本机(服务器)IP和端口
    //sockaddr结构中的信息
    if (SOCKET_ERROR == bind(socketServer, (SOCKADDR*)&saServer, sizeof(saServer)))
    {
        string ret = to_string(WSAGetLastError());
        MessageBoxA(0, "error_bind", ret.c_str(), 0);
        //释放stocket
        closesocket(socketServer);
        //清理网络库
        WSACleanup();
        return -1;
    }




        /*监听本机(服务器)的套接字*/

    if (SOCKET_ERROR == listen(socketServer, SOMAXCONN))
    {
        string ret = to_string(WSAGetLastError());
        MessageBoxA(0, "error_listen", ret.c_str(), 0);
        CloseHandle(set.Port);
        //释放stocket
        closesocket(socketServer);
        //清理网络库
        WSACleanup();
        return -1;
    }









    //创建一个完成端口
    set.Port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
    if ( 0 == set.Port)
    {
        string ret = to_string(WSAGetLastError());
        MessageBoxA(0, "error_listen", ret.c_str(), 0);
        //释放stocket
        closesocket(socketServer);
        //清理网络库
        WSACleanup();
        return -1;
    }
    //绑定sorket 和 完成端口  参数3是传入参数,发给函数GetQueuedCompletionStatus的参数3
    if (0 == CreateIoCompletionPort((HANDLE)socketServer, set.Port, 0, 0))
    {
        string ret = to_string(WSAGetLastError());
        MessageBoxA(0, "error_listen", ret.c_str(), 0);

        CloseHandle(set.Port);
        //释放stocket
        closesocket(socketServer);
        //清理网络库
        WSACleanup();
        return -1;
   }






    //创建线程,查询CPU是几核就创建几核
    SYSTEM_INFO lpSystemInfo;
    GetSystemInfo(&lpSystemInfo);
    set.ThreadNum = lpSystemInfo.dwNumberOfProcessors;
    set.Pthread = (PHANDLE)malloc(set.ThreadNum  * sizeof(HANDLE));
    set.ThreadOpen = true;

    /*创建线程来用于消息接收*/
    for (UINT i = 0; i < set.ThreadNum; i++)
    {
        set.Pthread[i] = CreateThread(0, 0, PTHREAD_ROUTINE, 0, 0, 0);
    }



    异步接收客户端
    if (0 == PostAccept())
    {
        clear();
    
        return 0;
    }



    while (set.ThreadOpen)
    {
        Sleep(1000);
    }

    return 1;
}


BOOL  WINAPI HANDLER_ROUTINE(_In_ DWORD CtrlType)
{
    switch (CtrlType)
    {
    case CTRL_CLOSE_EVENT:
    {
        set.ThreadOpen = false;
        clear();
    }
    default:
        break;
    }

    return true;
}


#include <fstream>
#include <string>
class person
{
public:
    int a;
    string b;
    int c;
};


int main()
{


    //创建个回调监视控制台关闭
    SetConsoleCtrlHandler(HANDLER_ROUTINE,true);
    create();

    //  create("127.0.0.1");


    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值