

HANDLE WINAPI CreateIoCompletionPort(_In_ HANDLE FileHandle, //已经打开的文件句柄或者空句柄,一般是客户端的句柄_In_opt_ HANDLE ExistingCompletionPort, //已经存在的IOCP句柄_In_ ULONG_PTR CompletionKey, //完成键,包含了指定I/O完成包的指定文件_In_ DWORD NumberOfConcurrentThreads //真正并发同时执行最大线程数,一般推介是CPU核心数*2);
HANDLE m_hIOCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0 );
2、socket与完成端口绑定:CreateIoCompletionPort(...);
CreateIoCompletionPort((HANDLE)Clietnt,m_hIOCompletionPort,(ULONG_PTR)PerHandleData,0)
BOOL WINAPI GetQueuedCompletionStatus(__in HANDLE CompletionPort, // 这个就是我们建立的那个唯一的完成端口__out LPDWORD lpNumberOfBytes, //这个是操作完成后返回的字节数__out PULONG_PTR lpCompletionKey, // 这个是返回我们建立完成端口的时候绑定的那个自定义结构体参数__out LPOVERLAPPED *lpOverlapped, // 这个是返回我们在连入Socket的时候一起建立的那个重叠结构__in DWORD dwMilliseconds // 等待完成端口的超时时间,如果线程不需要做其他的事情,那就INFINITE就行了);
struct _IO_DATA{int _Bytes;IO_OPERATION opCode;WSABUF wsabuf;OVERLAPPED m_Overlapped; //必要的,其余看你自己定义char buff[2048];};typedef struct 此结构体用来保存客户端的socket{SOCKET socket; //必要的SOCKADDR_STORAGE ClientAddr;}PER_HANDLE_DATA, *LPPER_HANDLE_DATA;
当然了还有:PostQueuedCompletionStatus(),该函数是向完成队列里面发送一个完成包,用来结束线程的也,还可以作为WASSend()来发送数据的。

大体上,按照流程图实现就没啥问题了。大家可以封装一个类,三个流程可以对应三个类函数。
这里的话要求大家自己去动手实现,这里不在多述了。
worker线程函数如下:
DWORD WINAPI _WorkerThread(LPVOID WordThreadPort){HANDLE g_hIocp=(HANDLE)WordThreadPort; //建立好的完成端口DWORD dwIoSize=0;LPPER_HANDLE_DATA lpCompletionKey=NULL; //结构体1变量LPOVERLAPPED lpOverlapped=NULL;_IO_DATA* _IO_Context=NULL; // 结构体2变量DWORD dwFlages=0;DWORD nBytes;int nRet=0;while(1){if(GetQueuedCompletionStatus(g_hIocp,&dwIoSize,(PULONG_PTR)&lpCompletionKey,(LPOVERLAPPED*)&lpOverlapped,INFINITE)!=true)cout<<"error"<<endl;_IO_Context=(_IO_DATA*)CONTAINING_RECORD(lpOverlapped,_IO_DATA,m_Overlapped);if(dwIoSize==0){cout<<"客户端断开连接....."<<endl;closesocket(lpCompletionKey->socket);delete _IO_Context;continue;}WaitForSingleObject(hMutex,INFINITE);cout<<"_IO_Context data:"<<_IO_Context->wsabuf.buf<<endl;ReleaseMutex(hMutex);memset(_IO_Context->wsabuf.buf,'\0',sizeof(_IO_Context->wsabuf.buf));ZeroMemory(&(_IO_Context->m_Overlapped),sizeof(OVERLAPPED));_IO_Context->wsabuf.len=2048;_IO_Context->wsabuf.buf=_IO_Context->buff;nRet=WSARecv(lpCompletionKey->socket,& _IO_Context->wsabuf,1,&nBytes,&dwFlages,&_IO_Context->m_Overlapped,NULL);if(nRet==SOCKET_ERROR&&(ERROR_IO_PENDING!=WSAGetLastError())){cout<<"失败:"<<WSAGetLastError()<<endl;closesocket(lpCompletionKey->socket);delete _IO_Context;continue;}}return 0;}
#include <iostream> 头文件#include <Winsock2.h>#include <windows.h>using namespace std;HANDLE hMutex = CreateMutex(NULL, FALSE, NULL); //用于打印Client发送过来的数据enum IO_OPERATION{IO_WRITE,IO_READ}; //读写状态枚举struct _IO_DATA{int _Bytes;IO_OPERATION opCode; //自行在代码里添加补充什么时候实现发送与接收的操作WSABUF wsabuf;OVERLAPPED m_Overlapped;char buff[2048];};typedef struct{SOCKET socket;SOCKADDR_STORAGE ClientAddr;}PER_HANDLE_DATA, *LPPER_HANDLE_DATA;DWORD WINAPI _WorkerThread(LPVOID WordThreadPort);
main函数:
int main(){HANDLE m_hIOCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0 );SYSTEM_INFO msi; //确定处理器的核心数量GetSystemInfo(&msi);for (int i = 0; i < msi.dwNumberOfProcessors*2; i++){HANDLE hThread=CreateThread(NULL, 0, _WorkerThread,m_hIOCompletionPort ,0,NULL);CloseHandle(hThread);}WSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsaData); //MAKEWORD(2, 2)版本号SOCKET _socket=WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);SOCKADDR_IN addrServer;addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//inet_addr("0.0.0.0");addrServer.sin_family = AF_INET;addrServer.sin_port = htons(81);bind(_socket, (SOCKADDR*)&addrServer, sizeof(SOCKADDR)); //绑定listen(_socket, 2);//监听cout<<"等待连接....."<<endl;while(1){int len = sizeof(SOCKADDR);SOCKADDR_IN addr;PER_HANDLE_DATA * PerHandleData = NULL;SOCKET Clietnt=accept(_socket,(SOCKADDR*)&addr,&len);cout<<"客户端连接成功......."<<endl;PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA)); // 在堆中为这个PerHandleData申请指定大小的内存PerHandleData -> socket = Clietnt;memcpy (&PerHandleData -> ClientAddr, &addr, len);if(CreateIoCompletionPort((HANDLE)Clietnt,m_hIOCompletionPort,(ULONG_PTR)PerHandleData,0)==NULL){cout<<"客户端绑定失败"<<endl;closesocket(Clietnt);}else{_IO_DATA* data=new _IO_DATA;data = (_IO_DATA*)GlobalAlloc(GPTR, sizeof(_IO_DATA));memset(&data->m_Overlapped,0,sizeof(data->m_Overlapped));data->opCode=IO_READ;data->wsabuf.buf=data->buff;data->wsabuf.len=2048;DWORD nByte,dwFalgs=0;int iRet=WSARecv(Clietnt,&data->wsabuf,1,&nByte,&dwFalgs,&data->m_Overlapped,NULL);if(iRet==SOCKET_ERROR&&(GetLastError()!=ERROR_IO_PENDING)){cout<<"接受失败"<<endl;closesocket(Clietnt);delete data;continue;}}}closesocket(_socket);WSACleanup();return 0;}

bool QQ_Users::Init_MySQL(){mysql_init(&user);if(NULL == mysql_real_connect(&user, "localhost", "root", password_.c_str(), "MYSQL", 3306, NULL, 0))return false;else return true;}
建立好以后,接着创建数据库和表了:
bool QQ_Users::create_database_table(const string sql){if (mysql_query(&user, sql.c_str())){cout << "line: " << __LINE__ << ";"<< mysql_error(&user) << mysql_errno(&user) << endl;return false;}cout<<"successfully established"<<endl<<endl;return true;}
最后,就是插入数据和读取数据了。

点击上方蓝字关注我们
文章转载自小懵白生活小趣谈,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




