老早寫過的IOCP模型demo程式碼;
僅供參考下!
#ifndef __IOCPMODEL_H #define __IOCPMODEL_H #include <iostream> #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib") #define OP_READ 1 #define OP_WRITE 2 #define OP_ACCEPT 3 #define OP_END -1 #define BUFFER_SIZE 1024 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; //IO操作型別 }PER_IO_DATA, *LPPER_IO_DATA; //執行緒方法 DWORD WINAPI ServerWorkerThread(LPVOID lpParam); #endif
CPP檔案
// IocpModel.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include "IocpModel.h" #define Op_READ 1 #define Op_WRITE 2 WSADATA wsa; HANDLE CompletionPort; SYSTEM_INFO Systeminfo; SOCKADDR_IN InternetAddr; HANDLE ThreadHanle; void ChangeHandleData(LPPER_IO_DATA lpPerIoContext,int state) { /** Fucntion Description: 根據傳進來的state,來進行改變下一步的IO操作 Parameter: lpPerIoContext:上一個IO操作的結果 state 上一個IO操作的狀態 Return Value: 返回值為空 **/ if(OP_READ == state) { //完成了讀取客戶端資料,並且返回資料 lpPerIoContext->OperationType = OP_WRITE; ZeroMemory(&(lpPerIoContext->Overlapped),sizeof(OVERLAPPED)); //返回資料給客戶端 char *sendClientData = "sendClientData"; lpPerIoContext->DataBuf.buf = sendClientData; lpPerIoContext->DataBuf.len = BUFFER_SIZE; } if(OP_WRITE == state) { //上一個IO資料傳送客戶端完成,結束就用 OP_END //繼續接受,叫型別設定為OP_READ,注意清空下 buff //繼續傳送,將資料設定為OP_WRITE lpPerIoContext->OperationType = OP_READ; lpPerIoContext->DataBuf.buf = lpPerIoContext->buffer; lpPerIoContext->DataBuf.len = BUFFER_SIZE; } if(OP_ACCEPT == state) { //立起來的連線,把控制代碼設為讀型別 lpPerIoContext->OperationType = OP_READ; ZeroMemory(&(lpPerIoContext->Overlapped),sizeof(OVERLAPPED)); ZeroMemory(&(lpPerIoContext->DataBuf),sizeof(lpPerIoContext->DataBuf)); lpPerIoContext->DataBuf.buf = lpPerIoContext->buffer; lpPerIoContext->DataBuf.len = BUFFER_SIZE; cout << "資料包操作型別被改為 : OP_READ"<<endl; } } void SendHandleData(LPPER_IO_DATA lpPerIoContext,LPPER_HANDLE_DATA perHandData) { /** 根據lpPerIoContext物件OperationType來進行下一步的操作 **/ DWORD dwIosize = 0; int nResult =0; DWORD RecvBytes = 0; DWORD nFlag = 0; if(lpPerIoContext->OperationType == OP_WRITE) { /*傳送資料到客戶端*/ nResult = WSASend(perHandData->Socket,&(lpPerIoContext->DataBuf),1,&dwIosize,0,&(lpPerIoContext->Overlapped),NULL); if((nResult == SOCKET_ERROR) && WSAGetLastError() != ERROR_IO_PENDING ) { cout<< "WSASend error :"<<WSAGetLastError()<<endl; ::closesocket(perHandData->Socket); return; } } else if(lpPerIoContext->OperationType == OP_READ) { //清空,準備下個I/O資料 ZeroMemory(&(lpPerIoContext->Overlapped),sizeof(OVERLAPPED)); //注意:這裡清空下buffer,要不然資料會跟上一條粘在一起 ZeroMemory(&(lpPerIoContext->buffer),sizeof(lpPerIoContext->buffer)); lpPerIoContext->DataBuf.len = BUFFER_SIZE; if(SOCKET_ERROR == WSARecv(perHandData->Socket, &(lpPerIoContext->DataBuf), 1,&RecvBytes,&nFlag,&(lpPerIoContext->Overlapped),NULL)){ cout << "WSARecv() failed: " << WSAGetLastError() << endl; return; } } else if(lpPerIoContext->OperationType == OP_END) { ::closesocket(perHandData->Socket); } } int main() { SOCKET ListenSock; SOCKET accpSocket; PER_HANDLE_DATA *PerHandleData = NULL; SOCKADDR_IN saRemote; int RemoteLen; cout<<"Server start......"<<endl; WSAStartup(MAKEWORD(2,2),&wsa); GetSystemInfo(&Systeminfo); //建立一個IO完成埠 CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0); if ( CompletionPort == INVALID_HANDLE_VALUE ) { cout<<"完成埠建立失敗!!!!"<<endl; return 0; } //建立IOCP工作執行緒(根據CPU個數 * 2) for(int i = 0;i< Systeminfo.dwNumberOfProcessors * 2 ; ++ i) { //建立執行緒 ThreadHanle = CreateThread(NULL,0,ServerWorkerThread,CompletionPort,0,NULL); CloseHandle(ThreadHanle); } //4. 建立一個監聽套接字, ListenSock = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED); if(ListenSock == INVALID_SOCKET) { cout<<"套接字建立 失敗!!"<<endl; return 0; } InternetAddr.sin_family = AF_INET; InternetAddr.sin_port = htons(5000); InternetAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); if(SOCKET_ERROR == bind(ListenSock,(SOCKADDR*)&InternetAddr,sizeof(InternetAddr))) { cout<<"伺服器繫結地址資訊 失敗!! errid:"<<GetLastError()<<endl; closesocket(ListenSock); return 0; } int ret = listen(ListenSock, 5); if (ret == SOCKET_ERROR) { cout<<"監聽套接字失敗!! errid:"<<GetLastError()<<endl; closesocket(ListenSock); return 0; } while(TRUE) { //接受連線 RemoteLen = sizeof(saRemote); //accpSocket = WSAAccept(ListenSock,NULL,NULL,NULL,0); accpSocket = accept(ListenSock, (SOCKADDR*)&saRemote, &RemoteLen); if(SOCKET_ERROR == accpSocket) { cout<<"接受套接字錯誤!! errid:"<<GetLastError()<<endl; closesocket(accpSocket); return 0; } //建立用來和套接字關聯控制代碼資訊結構 PerHandleData =(LPPER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA)); if(PerHandleData == NULL) { cout<<"PerHandleData = null!! errid:"<<GetLastError()<<endl; closesocket(accpSocket); return 0; } cout<< "Socker number: "<< accpSocket << " connected" << endl; PerHandleData->Socket = accpSocket; memcpy(&PerHandleData->ClientAddr,&saRemote,RemoteLen); //將接受的套接字關聯到 完成埠 if(CreateIoCompletionPort((HANDLE)accpSocket,CompletionPort,(DWORD)PerHandleData,0) == NULL) { cout<<"create complertion port error! errid:"<<GetLastError()<<endl; return 0; } LPPER_IO_DATA PerIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_DATA));; ChangeHandleData(PerIoData,OP_ACCEPT); SendHandleData(PerIoData,PerHandleData); } return 0; } //建立執行緒函式 DWORD WINAPI ServerWorkerThread(LPVOID lpParam) { HANDLE CompletionPort = (HANDLE)lpParam; DWORD ByresTransferred; LPOVERLAPPED lpOverlapped = NULL; LPPER_HANDLE_DATA PerHandleData = NULL; //LPPER_IO_DATA PerHandleData = NULL; LPPER_IO_DATA PerIoData = NULL; DWORD SendBytes; DWORD RecvBytes = 0; DWORD Flags = 0; BOOL bRet = FALSE; while (TRUE) { bRet = GetQueuedCompletionStatus(CompletionPort, &ByresTransferred, //的I/O操作所傳送資料的位元組數 (PULONG_PTR)&PerHandleData, //用於存放與之關聯的Completion鍵 (LPOVERLAPPED*)&lpOverlapped, INFINITE); if(!bRet) { closesocket(PerHandleData->Socket); ::GlobalFree(PerHandleData); ::GlobalFree(PerIoData); ::GlobalFree(lpOverlapped); cout<< "失去客戶端連線!!!!" << bRet <<endl; return 0; } PerIoData = (LPPER_IO_DATA)lpOverlapped; //先檢查一下,看看是否套接字有錯誤發生 if(0 == ByresTransferred) { if(SOCKET_ERROR == closesocket(PerHandleData->Socket)){ cout<< "ByresTransferred SOCKET_ERROR err:" << GetLastError() << endl; } ::GlobalFree(PerHandleData); ::GlobalFree(PerIoData); cout<< "發生錯誤! error" <<endl; continue; } //處理操作 switch(PerIoData->OperationType) { case OP_ACCEPT: if(ByresTransferred) { //第一次連線接受到的資料 ChangeHandleData(PerIoData,OP_ACCEPT); SendHandleData(PerIoData,PerHandleData); } else { //連線成功,資料沒接受到,繼續接受 ChangeHandleData(PerIoData,OP_ACCEPT); SendHandleData(PerIoData,PerHandleData); } break; case OP_READ: cout<<"-----------------reader----------------------"<< endl; cout<<"傳送資料的位元組數:"<< ByresTransferred <<endl; cout<<"接受資料為:"<<PerIoData->DataBuf.buf<< endl; cout<<"---------------------------------------------"<< endl; ChangeHandleData(PerIoData,OP_READ); SendHandleData(PerIoData,PerHandleData); break; case OP_WRITE: ChangeHandleData(PerIoData,OP_WRITE); SendHandleData(PerIoData,PerHandleData); break; default: //其他操作 break; } } return 0 ; }
相關推薦
老早寫過的IOCP模型demo程式碼;
僅供參考下! #ifndef __IOCPMODEL_H #define __IOCPMODEL_H #include <iostream> #include <WinSock2.h> #pragma comment(lib,"ws2_32.
轉發:IOCP模型示例程式碼
#include <WinSock2.h> #include <Windows.h> #include <vector> #include <iostream> using namespace std; #pragma co
寫了8年的程式碼,做過的專案都下線了,程式設計師的意義在哪裡!
一、起因 前幾天專案交付上線,所以閒下來了。忽然想起來,自己業餘接的活,有些專案已經不再運營了,所以想清理下域名解析。 上去阿里雲一看,總的大概有15個解析。這15個解析就意味著15個專案。這些專案都是我去談的需求、寫的文件、前後端開發、部署上線維護,整個專案幾乎都是我一人完成的。 想當初,很用心的去開
看看這些被同事噴的JS程式碼風格你寫過多少
作者:殷榮檜@騰訊 目錄: 一、變數相關 二、函式相關 三、儘量使用ES6,有可以能的話ES7中新語法 現在寫程式碼比以前好多了,程式碼的格式都有eslint,prettier,babel(寫新版語法)這些來保證,然而,技術手段再高階都不能解決程式碼可讀性(程式碼能否被未來的自己和同事看懂)的問
程式設計師入職華為三個月沒寫過程式碼:渴望提交程式碼,創造價值!
一名程式設計師,由於公司的專案情況,長期不能寫程式碼,你是什麼感受呢?是不是感覺很失落,大部分程式設計師都會有這種感覺吧,有的時候可能是研究一些技術,看一些程式碼什麼的,部分程式設計師就不願意幹這樣的事情,感覺還是自己寫程式碼爽,最近就有一名華為員工經歷了這樣一種情況!
一個模型搞定所有風格轉換,直接在瀏覽器實現(demo+程式碼)
用一個模型就能實現所有型別的風格轉換!一個名為Arbitrary Image Stylization in the Browser的專案最近火起來。 作者是日本小哥Reiichiro Nakano,他用TensorFlow.js在瀏覽器中構建了一個使用任意影象進行風格化的demo。 不像以前
Java - JDK8新特性,程式碼demo示例;
哈哈哈哈大魔都下雪啦,敲段程式碼暖和暖和,嘿嘿 public class jdk8Test { @Test public void LambdaNew() { //before jdk8 List<String> names = Arrays.asList
寫了8年的程式碼,做過的專案都下線了,程式設計師的意義在哪裡?
我堅信未來是我的,也是你的。但歸根結底是程式設計師的! ——忘記來自哪裡了 程式碼,正在改變世界。正是因為有了程式碼的存在,才有了百度、阿里巴巴、騰訊、京東、等的存在...... 下面是一位來自工作了八年的資深碼農的深刻感悟,正值“1024 程式設計
十行以內,你寫過哪些比較酷的 Matlab 程式碼?
最近正在寫一個模擬快速畫圖的GUI。 以下這段的功能是,點一下按鈕,就把打開了的Scope的圖直接儲存成jpg檔案。 以前的話基本都是用截圖工具,或者先把Scope的Menubar設定成可見,之後再Save as為影象。 刪掉了備註,剛好十行,可卻花了好幾天的時間找如何定位到特定object的方法…
從div盒子模型談如何寫可維護的css程式碼
在寫頁面之中,width, margin, padding這三個CSS屬性可以說是用到頻率最高的幾個屬性之一。但根據我的觀點來看,許多人,甚至於大多數前端對於這三個屬性的書寫把握上乏善可陳,以至於相容和靈活性不得兼顧,導致日後的開發維護成本直線上升,程式碼不斷增長,覆蓋重寫樣式,接著再修復一個又一個的Bu
netty的執行緒模型, 調優 及 獻上寫過註釋的原始碼工程
Netty能幹什麼? Http伺服器 使用Netty可以編寫一個 Http伺服器, 就像tomcat那樣,能接受使用者傳送的http請求, , 只不過沒有實現Servelt規範, 但是它也能解析攜帶的引數, 對請求的路徑進行路由導航, 從而實現將不同的請求導向不同的handler進行處理 對socket與RP
主從復制2——擁有海量數據主服務器的主從復制模型詳細實現;
海量數據的主從復制實現基本策略:此時需要在主服務器上先完全備份,還原到從服務器;接著開啟主從復制; 如果直接使用主從復制,那麽主從服務器的壓力很大;主服務器數據全備份操作: [root@master ~]$mysqldump -A -F --single-transaction --master-data=1
【HiJ1m】在NOIP2017前寫過的有用的東西匯總
cnblogs 技巧 bst div 方程 ima alt 技術分享 pos http://www.cnblogs.com/Elfish/p/7544623.html 高級樹狀數組 http://www.cnblogs.com/Elfish/p/7554420.html
代寫編程、代寫機器學習模型、代寫AI python
nal prolog 一份 行業 之間 標識 日期 軟件設計 環境 代寫編程、代寫機器學習模型基於不同的機器學習模型,利用大量的特征變量,對標的資產價格的波動進行預測研究,並對預測效果進行評價。機器學習的模型包括,但不限於XGBoost、GBDT、LSTM等經典學習模型。待
原生JS寫了一個小demo,根據輸入的數字生成不同背景顏色的小方塊兒~
top == UNC 定位元素 demo TE tostring eight 地方 昨天練習寫了這個小demo,個人覺得通過設置定位元素left和top的值,來實現換行的功能,這種方法很巧妙~ 另外,如下代碼中的隨機顏色的獲取,還請各位前輩多多指教:需要改進的地方;或者有
使用L2正則化和平均滑動模型的LeNet-5MNIST手寫數字識別模型
put 輸出矩陣 conv2 cross -m collect variable global 空間 使用L2正則化和平均滑動模型的LeNet-5MNIST手寫數字識別模型 覺得有用的話,歡迎一起討論相互學習~Follow Me 參考文獻Tensorflow實戰Googl
kaldi中文語音識別thchs30模型訓練程式碼功能和配置引數解讀
Monophone 單音素模型的訓練 # Flat start and monophone training, with delta-delta features. # This script applies ceps
從零開始的Python爬蟲速成指南,本文受眾:沒寫過爬蟲的萌新
引言 用最短的時間寫一個最簡單的爬蟲,可以抓一些簡單的論壇、帖子、網頁。 入門 1.準備工作 安裝Python 安裝scrapy框架 一個IDE或者可以用自帶的 2.開始寫爬蟲 &n
寫過的部分板子
退役之前把自己敲過的板子都發一下,不會有詳細的解釋,只能保證碼風適合大部分人的閱讀習慣 你將會在這篇文章中看到這些模板: ·快讀 ·最短路——dijkstra及spfa ·最小生成樹 ·LCA的tarjan演算法 ·強連通分量的tarjan演算法以及割點的tarja
請寫出一段Python程式碼實現刪除一個list裡面的重複元素?
方法1:使用set函式 s=set(list),然後再list(s) 方法2:append 1 def delList(L): 2 L1 = [] 3 for i in L: 4