日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

个人IOCP服务器例子解说

發布時間:2024/4/11 编程问答 56 豆豆
生活随笔 收集整理的這篇文章主要介紹了 个人IOCP服务器例子解说 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這里寫兩方面的解說,一方面,解說iocp內部處理情況(這部分以個人查考寫的iocp服務器和客戶端寫的);一方面,參考libeventlibevent-1.4.4-iocp-3 大致調整給出一個比較標準的服務器和客戶端例子。新手可以通過前部分獲得建立iocp的基本理解;通過后部分建立自己(基于libevent)標準的iocp代碼。

?

一、//先來建立自己的icop吧

?

1)自己的iocp服務器(MyIOCPServer.cpp)

?

#include "stdafx.h"
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <iostream>
using namespace std;

// 單句柄數據
typedef struct tagPER_HANDLE_DATA
{
?SOCKET Socket;
?SOCKADDR_STORAGE ClientAddr;
?// 將和這個句柄關聯的其他有用信息,盡管放在這里面吧

}PER_HANDLE_DATA, *LPPER_HANDLE_DATA;

// 但I/O 操作數據
typedef struct tagPER_IO_DATA
{
?OVERLAPPED Overlapped;
?WSABUF DataBuf;
?char buffer[1024];
?int BufferLen;
?int OperationType; // 可以作為讀寫的標志,為簡單,我忽略了
}PER_IO_DATA, *LPPER_IO_DATA;

//線程函數
DWORD WINAPI ServerWorkerThread(LPVOID lpParam);

DWORD WINAPI ServerWorkerThread(LPVOID lpParam)
{
?HANDLE CompletionPort = (HANDLE)lpParam;
?DWORD BytesTransferred;
?LPOVERLAPPED lpOverlapped;
?LPPER_HANDLE_DATA PerHandleData = NULL;
?LPPER_IO_DATA PerIoData = NULL;
?DWORD SendBytes;
?DWORD RecvBytes;
?DWORD Flags;
?BOOL bRet = FALSE;

?while (TRUE) //無限循環
?{
??bRet = GetQueuedCompletionStatus(CompletionPort,&BytesTransferred,(PULONG_PTR)&PerHandleData,(LPOVERLAPPED*)&lpOverlapped,INFINITE);

??// 檢查成功的返回,這兒要注意使用這個宏CONTAINING_RECORD
??PerIoData = (LPPER_IO_DATA)CONTAINING_RECORD(lpOverlapped,PER_IO_DATA,Overlapped);
??// 先檢查一下,看看是否在套接字上已有錯誤發生

??if (0 == BytesTransferred)
??{
???closesocket(PerHandleData->Socket);
???GlobalFree(PerHandleData);
???GlobalFree(PerIoData);
???continue;
??}

??// 數據處理
??char sendBuf[100];
??sprintf(sendBuf,"Welcome %s to? %d %d \n",PerIoData->DataBuf.buf,PerHandleData->Socket,::GetCurrentThreadId());
??send(PerHandleData->Socket,sendBuf,strlen(sendBuf)+1,0);
??//WSASend()
???/*DataBuf.len = DATA_BUFSIZE;?
??  DataBuf.buf = buffer;   
??? for(i=0; i < SEND_COUNT ;i++) {   
???? WSASend(PerHandleData->Socket, &DataBuf, 1,   &SendBytes, 0, &SendOverlapped, NULL); */


??// 成功了!!!這兒就收到了來自客戶端的數據
??cout << PerIoData->DataBuf.buf << ::GetCurrentThreadId() << endl;

??Flags = 0;
??// 為下一個重疊調用建立單I/O 操作數據
??ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));

??PerIoData->DataBuf.len = 1024;
??PerIoData->DataBuf.buf = PerIoData->buffer;
??PerIoData->OperationType = 0; // read

??WSARecv(PerHandleData->Socket,&(PerIoData->DataBuf),1,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
?}
?return 0;
}

int main(int argc, _TCHAR* argv[])
{
?//頭部申明
?HANDLE CompletionPort;
?WSADATA wsd;
?SYSTEM_INFO SystemInfo;
?SOCKADDR_IN InternetAddr;
?SOCKET Listen;

?// 加載WinSock2.2
?WSAStartup(MAKEWORD(2, 2), &wsd);

?// 1.創建一個I/O 完成端口
?CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);

?// 2.確定系統中有多少個處理器
?GetSystemInfo(&SystemInfo);

?// 3.基于系統中可用的處理器數量創建工作器線程
?for (int i = 0; i < int(SystemInfo.dwNumberOfProcessors * 2); ++i)
?{
??HANDLE ThreadHandle;
??// 創建一個服務器的工作器線程,并將完成端口傳遞到該線程
??ThreadHandle = CreateThread(NULL,0,ServerWorkerThread,CompletionPort,0,NULL);
??CloseHandle(ThreadHandle);
?}

?// 4.創建一個監聽套接字,以下的套路都是固定的。
?Listen = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);

?//綁定和監聽
?InternetAddr.sin_family = PF_INET;
?InternetAddr.sin_port = htons(6000);
?InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
?bind(Listen, (SOCKADDR*)&InternetAddr, sizeof(InternetAddr));
?listen(Listen, 5);

?//無限循環
?BOOL b = TRUE;
?while (b)
?{
??PER_HANDLE_DATA * PerHandleData = NULL;
??SOCKADDR_IN saRemote;
??SOCKET Accept;
??int RemoteLen;
??// 5.接收連接,并分配完成端口,這兒可以用AcceptEx 來代替,以創
??// 建可伸縮的Winsock 應用程序。
??RemoteLen = sizeof(saRemote);
??Accept = accept(Listen, (SOCKADDR*)&saRemote, &RemoteLen);

??// 6.創建用來和套接字關聯的單句柄數據信息結構
??PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));

??//cout << "Socket number " << Accept << " connected" << endl;

??PerHandleData->Socket = Accept;
??memcpy(&PerHandleData->ClientAddr, &saRemote, RemoteLen);

??// 7.將接受套接字和完成端口關聯起來
??CreateIoCompletionPort((HANDLE)Accept,CompletionPort,(DWORD)PerHandleData,0);

??// 開始在接受套接字上處理I/O
??// 使用重疊I/O 機制,在新建的套接字上投遞一個或多個異步
??// WSARecv 或 WSASend 請求。這些I/O 請求完成后,工作者線程
??// 會為I/O 請求提供服務,之后就可以坐享其成了
??static int const DATA_BUFSIZE = 4096;?
??DWORD RecvBytes = 0;
??DWORD Flags = 0;

??// 單I/O 操作數據
??LPPER_IO_DATA PerIoData = NULL;
??PerIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_DATA));
??ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
??PerIoData->DataBuf.len = 1024;
??PerIoData->DataBuf.buf = PerIoData->buffer;
??PerIoData->OperationType = 0; // read
??WSARecv(PerHandleData->Socket,&(PerIoData->DataBuf),1,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
?}

?return 0;
}

?

?

2)自己的iocp客戶端(MyIOCPClient.cpp)

?

#include "stdafx.h"
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <stdio.h>

void main()
{
?WORD wVersionRequested;
?WSADATA wsaData;
?int err;

?wVersionRequested = MAKEWORD( 1, 1 );

?err = WSAStartup( wVersionRequested, &wsaData );
?if ( err != 0 ) {
??return;
?}


?if ( LOBYTE( wsaData.wVersion ) != 1 ||
??HIBYTE( wsaData.wVersion ) != 1 ) {
???WSACleanup( );
???return;?
?}

?while (true)
?{
??SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);

??SOCKADDR_IN addrSrv;
??addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
??addrSrv.sin_family=AF_INET;
??addrSrv.sin_port=htons(6000);
??connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

??send(sockClient,"This is lisi",strlen("This is lisi")+1,0);

??char recvBuf[100];
??recv(sockClient,recvBuf,100,0);
??printf("%s\n",recvBuf);

??closesocket(sockClient);
?}

?WSACleanup();
}

總結

以上是生活随笔為你收集整理的个人IOCP服务器例子解说的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。