iocp之簡單實現

2021-08-22 04:55:57 字數 3961 閱讀 4359

1、標頭檔案

#include #include #ifdef _windows

#pragma comment(lib,"ws2_32.lib") //socket程式設計需用的動態鏈結庫

#pragma comment(lib,"kernel32.lib") //iocp需要用到的動態鏈結庫

#endif

//log_view->log(str, ...) 功能:輸出日誌到介面

2、載入套接字型檔

bool iocpserver::loadsockdll()

if (lobyte(wsa.wversion) != 2 || hibyte(wsa.wversion) != 2)

return true;

}

3、建立iocp+建立iocp工作執行緒

bool iocpserver::initiocp()

log_view->log("建立iocp處理執行緒...");

system_info info;

getsysteminfo(&info);

for (int i = 0; i < info.dwnumberofprocessors*2; ++i)

return true;

}

createiocompletionport引數說明:

param:有效的檔案控制代碼 或 invalid_handle_value(一般用這個)

param:null(新建iocp時)

param:0。

param:作業系統允許同時處理i/o完成埠資料報的最大執行緒數,如果此引數為零,則最大執行緒數等於cpu數量。

建立的工作執行緒數量為cpu數量*2,考慮到執行緒查詢修改資料庫時有等鎖的情況,多餘的執行緒可以替補。

4、建立socket、繫結、監聽+建立接收客戶端連線請求執行緒

bool iocpserver::initsocket(const string& ip, unsigned short port)

log_view->log("繫結");

sockaddr_in addr;

addr.sin_family = af_inet;

addr.sin_port = htons(port);

addr.sin_addr.s_un.s_addr = inet_addr(ip.c_str());

if(0 != ::bind(m_socket, (sockaddr*)&addr, sizeof(addr)))

log_view->log("監聽");

if (0 != listen(m_socket, 100))

log_view->log("建立accept執行緒");

m_accpetthread = new thread(std::bind(&iocpserver::acceptproc, this));

return true;

}

5、接收客戶端連線請求執行緒

void iocpserver::acceptproc()

//將iocp埠與客戶端socket繫結

createiocompletionport((handle)clientsocket, m_iocp, (ulong_ptr)clientsocket, 0);

//通知新增連線,收到通知的模組處理為客戶端建立會話物件

string ip = inet_ntoa(addr.sin_addr);

unsigned short port = htons(addr.sin_port);

if (!m_notify->addconnect(clientsocket, ip, port))

//為客戶端投遞接收請求

siocpcontent* ct = new siocpcontent(buff_len, eiocptype::iocprecv);

if (!deliveryrecvrequest(clientsocket, ct))

}log_view->log("accept執行緒自然退出");

}

createiocompletionport引數說明:

param:有效的檔案控制代碼 或 invalid_handle_value,這裡用客戶端socket

param:現有i/o完成埠的控制代碼(與socket繫結時)

param:傳送給處理函式的引數,即傳給getqueuedcompletionstatus第三個引數

param:作業系統允許同時處理i/o完成埠資料報的最大執行緒數,如果此引數為零,則最大執行緒數等於cpu數量。

6、iocp工作執行緒

void iocpserver::workerproc(int tag)

else} }

log_view->log("iocp執行緒[%d]自然退出", tag);

}

getqueuedcompletionstatus引數說明

param:之前建立的iocp埠

param:收到的資料長度

param:iocp埠與socket繫結時,createiocompletionport的第三個引數

param:投遞請求時,createiocompletionport的第六個引數,是個指標

param:等待通知的時間,infinite即一直等

7、為客戶端投遞接收請求

bool iocpserver::deliveryrecvrequest(unsigned sock, siocpcontent *content)

else if (ret == socket_error && wsagetlasterror() != wsa_io_pending)

return true;

}

8、釋放資源(憤怒地寫在一起)

//執行緒自然退出標誌

m_stopthread = true;

//釋放socket

if (invalid_socket != m_socket)

if (m_accpetthread)

delete m_accpetthread;

m_accpetthread = null;

log_view->log("accept執行緒結束");

}//釋放iocp相關

if (m_iocp)

for (size_t i = 0; i < m_workerthread.size(); ++i)

;itoa(i+1, buff, 10);

if (m_workerthread[i]->joinable())

log_view->log("執行緒結束:", i+1);

delete m_workerthread[i];

}m_workerthread.clear();

//解除安裝套接字型檔

wsacleanup();

9、siocpcontent結構體

#include #define buff_len    (1024)

enum eiocptype

;struct siocpcontent

siocpcontent(char* buff, int len)

~siocpcontent()

};

IOCP簡單實現

本人工作是服務端效能測試,因工作需要開發機械人框架,選用底層的時候看到網上滿大街的iocp介紹,還有說iocp比wsaasyncselect複雜等等,所以只好轉wsaasyncselect實現。因併發客戶端需要進行除錯測試,壓力測試工具作為客戶端來說效能十分重要,沒有經過測試的鬼知道秒併發多少請求,...

簡單的iocp例子

include include include include include using namespace std define i port 1666 define i addr 0.0.0.0 define dft buffer size 4096 define opt read 0 def...

IOCP 實現的基本步驟

呼叫iocp的步驟如下 抽象出乙個完成埠大概的處理流程 1 建立乙個完成埠。2 建立乙個執行緒a 3 a執行緒迴圈呼叫getqueuedcompletionstatus 函式來得到i o操作結果,這個函式是阻塞函式 4 主線程迴圈裡呼叫accept等待客戶端連線上來。5 主線程裡accept返回新連...