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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

事件通知方式实现的重叠I/O模型

發(fā)布時(shí)間:2024/4/11 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 事件通知方式实现的重叠I/O模型 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
//
/// 事件通知方式實(shí)現(xiàn)的重疊I/O模型(異步IO模型)
/// 這個(gè)模型的基本的設(shè)計(jì)實(shí)現(xiàn)是允許應(yīng)用程序使用重疊的數(shù)據(jù)結(jié)構(gòu)一次投遞一個(gè)或者多個(gè)異步I/O
/// 請(qǐng)求
/// 這個(gè)模型與上述其他模型不同的是它使用Winsock2提供的異步I/O函數(shù)WSARecv。在調(diào)用WSARecv
/// 時(shí),指定一個(gè)WSAOVERLAPPED結(jié)構(gòu),這個(gè)調(diào)用不是阻塞的,也就是說,它會(huì)立刻返回。一旦有
/// 數(shù)據(jù)到達(dá)的時(shí)候,被指定的WSAOVERLAPPED結(jié)構(gòu)中的hEvent被Signaled。由于下面這個(gè)語句
/// g_CliEventArr[g_iTotalConn] = g_pPerIODataArr[g_iTotalConn]->overlap.hEvent;
/// 使得與該套接字相關(guān)聯(lián)的WSAEVENT對(duì)象也被Signaled,所以WSAWaitForMultipleEvents的調(diào)用
/// 操作成功返回。我們現(xiàn)在應(yīng)該做的就是用與調(diào)用WSARecv相同的WSAOVERLAPPED結(jié)構(gòu)為參數(shù)調(diào)用
/// WSAGetOverlappedResult,從而得到本次I/O傳送的字節(jié)數(shù)等相關(guān)信息。在取得接收的數(shù)據(jù)后,
/// 把數(shù)據(jù)原封不動(dòng)的發(fā)送到客戶端,然后重新激活一個(gè)WSARecv異步操作。
//
//
/// 老陳:服務(wù)器應(yīng)用程序,信箱:Socket,幾樓幾號(hào):服務(wù)器內(nèi)存
/// 后來,微軟通過調(diào)查發(fā)現(xiàn),老陳不喜歡上下樓收發(fā)信件,因?yàn)樯舷聵瞧鋵?shí)很浪費(fèi)時(shí)間。
/// 于是微軟再次改進(jìn)他們的信箱。新式的信箱采用了更為先進(jìn)的技術(shù),只要用戶告訴微軟
/// 自己的家在幾樓幾號(hào),新式信箱會(huì)把信件直接傳送到用戶的家中,然后告訴用戶,你的
/// 信件已經(jīng)放到你的家中了!老陳很高興,因?yàn)樗槐卦儆H自收發(fā)信件了!?
//

#include?<winsock2.h>
#include?<stdio.h>
#define?PORT 5150
#define?MSGSIZE 1024
#pragma?comment(lib,?"ws2_32.lib")
typedef?struct
{
?WSAOVERLAPPED overlap;
//為了使用重疊I/O,每一個(gè)I/O函數(shù)都要接受一個(gè)WSAOVERLAPPED結(jié)構(gòu)類型的參數(shù)

?WSABUF Buffer;
?char?szMessage[MSGSIZE];
?DWORD NumberOfBytesRecvd;
?DWORD Flags;
}PER_IO_OPERATION_DATA,?*LPPER_IO_OPERATION_DATA;
int?g_iTotalConn?=?0;
SOCKET?g_CliSocketArr[MAXIMUM_WAIT_OBJECTS];
WSAEVENT g_CliEventArr[MAXIMUM_WAIT_OBJECTS];
LPPER_IO_OPERATION_DATA g_pPerIODataArr[MAXIMUM_WAIT_OBJECTS];
DWORD WINAPI WorkerThread(LPVOID);
void?Cleanup(int);
int?main()
{
?WSADATA wsaData;
?SOCKET?sListen,?sClient;
?SOCKADDR_IN?local,?client;
?DWORD dwThreadId;
?int?iaddrSize?=?sizeof(SOCKADDR_IN);
?
// Initialize Windows Socket library

?WSAStartup(0x0202,?&wsaData);
?
// Create listening socket

?sListen?=?::WSASocket(AF_INET,?SOCK_STREAM,?IPPROTO_TCP,NULL,0,WSA_FLAG_OVERLAPPED);
?
// Bind

?local.sin_addr.S_un.S_addr?=?htonl(INADDR_ANY);
?local.sin_family?=?AF_INET;
?local.sin_port?=?htons(PORT);
?bind(sListen,?(struct?sockaddr?*)&local,?sizeof(SOCKADDR_IN));
?
// Listen

?listen(sListen,?3);
?
// Create worker thread

?CreateThread(NULL,?0,?WorkerThread,?NULL,?0,?&dwThreadId);
?while?(TRUE)
?{
??
// Accept a connection

??sClient?=?accept(sListen,?(struct?sockaddr?*)&client,?&iaddrSize);
??printf("Accepted client:%s:%d\n",?inet_ntoa(client.sin_addr),?ntohs(client.sin_port));
??g_CliSocketArr[g_iTotalConn]?=?sClient;
??
// Allocate a PER_IO_OPERATION_DATA structure

??g_pPerIODataArr[g_iTotalConn]?=?(LPPER_IO_OPERATION_DATA)HeapAlloc(
???GetProcessHeap(),
???HEAP_ZERO_MEMORY,
???sizeof(PER_IO_OPERATION_DATA));
??g_pPerIODataArr[g_iTotalConn]->Buffer.len?=?MSGSIZE;
??g_pPerIODataArr[g_iTotalConn]->Buffer.buf?=?g_pPerIODataArr[g_iTotalConn]->szMessage;
??g_CliEventArr[g_iTotalConn]?=?g_pPerIODataArr[g_iTotalConn]->overlap.hEvent?=?WSACreateEvent();
??
// Launch an asynchronous operation(發(fā)起一個(gè)異步的I/O操作)

??
//This function receives data from a connected socket.

??WSARecv(
???g_CliSocketArr[g_iTotalConn],
//Socket的標(biāo)示

???&g_pPerIODataArr[g_iTotalConn]->Buffer,
//接收數(shù)據(jù)的Buffer

???1,
???&g_pPerIODataArr[g_iTotalConn]->NumberOfBytesRecvd,
//Pointer to the number of bytes received by this call if the receive operation completes immediately

???&g_pPerIODataArr[g_iTotalConn]->Flags,
???&g_pPerIODataArr[g_iTotalConn]->overlap,
//LPWSAOVERLAPPED結(jié)構(gòu)的參數(shù)

???NULL);
??g_iTotalConn++;
?}
?closesocket(sListen);
?WSACleanup();
?return?0;
}
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
?int?ret,?index;
?DWORD cbTransferred;
?while?(TRUE)
?{
??ret?=?WSAWaitForMultipleEvents(g_iTotalConn,?g_CliEventArr,?FALSE,?1000,?FALSE);
??
//注意這里應(yīng)該有相應(yīng)的修正的地方,WSAWaitForMultipleEvents函數(shù)在fWaitAll設(shè)置成FALSE

??
//的時(shí)候只能指定一個(gè)事件對(duì)象受信,解決方法使用for循環(huán)進(jìn)行循環(huán)檢測(cè)

??if?(ret?==?WSA_WAIT_FAILED?||?ret?==?WSA_WAIT_TIMEOUT)
??{
???continue;
??}
??index?=?ret?-?WSA_WAIT_EVENT_0;
??WSAResetEvent(g_CliEventArr[index]);
??
//獲得重疊I/O的操作的結(jié)果

??WSAGetOverlappedResult(
???g_CliSocketArr[index],
???&g_pPerIODataArr[index]->overlap,
???&cbTransferred,
???TRUE,
???&g_pPerIODataArr[g_iTotalConn]->Flags);
??if?(cbTransferred?==?0)
??{
???
// The connection was closed by client

???Cleanup(index);
??}
??else
??{
???
// g_pPerIODataArr[index]->szMessage contains the received data

???g_pPerIODataArr[index]->szMessage[cbTransferred]?=?'\0';
???
//這個(gè)是同步的I/O的操作哦

???send(g_CliSocketArr[index],?g_pPerIODataArr[index]->szMessage,\
????cbTransferred,?0);
???
// Launch another asynchronous operation

???WSARecv(
????g_CliSocketArr[index],
????&g_pPerIODataArr[index]->Buffer,
????1,
????&g_pPerIODataArr[index]->NumberOfBytesRecvd,
????&g_pPerIODataArr[index]->Flags,
????&g_pPerIODataArr[index]->overlap,
????NULL);
??}
?}
?return?0;
}
void?Cleanup(int?index)
{
?closesocket(g_CliSocketArr[index]);
?WSACloseEvent(g_CliEventArr[index]);
?HeapFree(GetProcessHeap(),?0,?g_pPerIODataArr[index]);
?if?(index?<?g_iTotalConn?-?1)
?{
??g_CliSocketArr[index]?=?g_CliSocketArr[g_iTotalConn?-?1];
??g_CliEventArr[index]?=?g_CliEventArr[g_iTotalConn?-?1];
??g_pPerIODataArr[index]?=?g_pPerIODataArr[g_iTotalConn?-?1];
?}
?g_pPerIODataArr[--g_iTotalConn]?=?NULL;
}

超強(qiáng)干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生

總結(jié)

以上是生活随笔為你收集整理的事件通知方式实现的重叠I/O模型的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。