• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牽著老婆滿街逛

            嚴以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            iocp進行SOCKET通信(轉載)

            轉載于hxzb7215191 的BLOG

            當然TCP方式的模型還有事件選擇模型。
            就是把所有的網絡事件和我們的一個程序里定義的事件梆定。
            這個有它的好處,可能可以讓我們更好的寫一個線程來管理
            接收與發送。
            現在來講一下一個完成端口模型。

            ? 完成端口
            ?
            ?一個完成端口其實就是一個通知隊列,由操作系統把已經完成的重疊I/O請求的通知
            ?放入其中。當某項I/O操作一旦完成,某個可以對該操作結果進行處理的工作者線程
            ?就會收到一則通知。而套接字在被創建后,可以在任何時候與某個完成端口進行關
            ?聯。
            ?
            ?步驟:
            ?1、創建一個空的完成端口;
            ?2、得到本地機器的CPU個數;
            ?3、開啟CPU*2個工作線程(又名線程池),全部都在等待完成端口的完成包;
            ?4、創建TCP的監聽socket,使用事件邦定,創建監聽線程;
            ?5、當有人連接進入的時候,將Client socket保存到一個我們自己定義的關鍵鍵,
            ??? 并把它與我們創建的完成端口關聯;
            ?6、使用WSARecv和WSASend函數投遞一些請求,這是使用重疊I/O的方式;
            ?7、重復5~6;

            ?注:1、重疊I/O的方式中,接收與發送數據包的時候,一定要進行投遞請求這是
            ???它們這個體系結構的特點
            ???當然,在完成端口方式中,不是直接使用的WSARecv和WSASend函數進行請求
            ???的投遞的。而是使用的ReadFile,Write的方式
            ??2、完成端口使用了系統內部的一些模型,所以我們只要按照一定的順序調用就
            ???可以完成了。
            ??3、完成端口是使用在這樣的情況下,有成千上萬的用戶連接的時候,它能夠
            ???保證性能不會降低。


            ?

            #include? < winsock2.h >
            #include?
            < windows.h >
            #include?
            < stdio.h >

            #define ?PORT?5150
            #define ?DATA_BUFSIZE?8192

            // 關鍵項
            typedef? struct
            {
            ???OVERLAPPED?Overlapped;
            ???WSABUF?DataBuf;
            ???CHAR?Buffer[DATA_BUFSIZE];
            ???DWORD?BytesSEND;
            ???DWORD?BytesRECV;
            }
            ?PER_IO_OPERATION_DATA,? * ?LPPER_IO_OPERATION_DATA;


            typedef?
            struct ?
            {
            ???SOCKET?Socket;
            }
            ?PER_HANDLE_DATA,? * ?LPPER_HANDLE_DATA;

            DWORD?WINAPI?ServerWorkerThread(LPVOID?CompletionPortID);

            void ?main( void )
            {
            ???SOCKADDR_IN?InternetAddr;
            ???SOCKET?Listen;
            ???SOCKET?Accept;
            ???HANDLE?CompletionPort;
            ???SYSTEM_INFO?SystemInfo;
            ???LPPER_HANDLE_DATA?PerHandleData;
            ???LPPER_IO_OPERATION_DATA?PerIoData;
            ???
            int ?i;
            ???DWORD?RecvBytes;
            ???DWORD?Flags;
            ???DWORD?ThreadID;
            ???WSADATA?wsaData;
            ???DWORD?Ret;

            ???
            if ?((Ret? = ?WSAStartup( 0x0202 ,? & wsaData))? != ? 0 )
            ???
            {
            ??????printf(
            " WSAStartup?failed?with?error?%d\n " ,?Ret);
            ??????
            return ;
            ???}


            ???
            // 打開一個空的完成端口

            ???
            if ?((CompletionPort? = ?CreateIoCompletionPort(INVALID_HANDLE_VALUE,?NULL,? 0 ,? 0 ))? == ?NULL)
            ???
            {
            ??????printf(?
            " CreateIoCompletionPort?failed?with?error:?%d\n " ,?GetLastError());
            ??????
            return ;
            ???}


            ???
            // ?Determine?how?many?processors?are?on?the?system.

            ???GetSystemInfo(
            & SystemInfo);

            ???
            // ?開啟cpu個數的2倍個的線程

            ???
            for (i? = ? 0 ;?i? < ?SystemInfo.dwNumberOfProcessors? * ? 2 ;?i ++ )
            ???
            {
            ??????HANDLE?ThreadHandle;

            ??????
            // ?Create?a?server?worker?thread?and?pass?the?completion?port?to?the?thread.

            ??????
            if ?((ThreadHandle? = ?CreateThread(NULL,? 0 ,?ServerWorkerThread,?CompletionPort,
            ?????????
            0 ,? & ThreadID))? == ?NULL)
            ??????
            {
            ?????????printf(
            " CreateThread()?failed?with?error?%d\n " ,?GetLastError());
            ?????????
            return ;
            ??????}


            ??????
            // ?Close?the?thread?handle
            ??????CloseHandle(ThreadHandle);
            ???}


            ???
            // 打開一個服務器socket

            ???
            if ?((Listen? = ?WSASocket(AF_INET,?SOCK_STREAM,? 0 ,?NULL,? 0 ,
            ??????WSA_FLAG_OVERLAPPED))?
            == ?INVALID_SOCKET)
            ???
            {
            ??????printf(
            " WSASocket()?failed?with?error?%d\n " ,?WSAGetLastError());
            ??????
            return ;
            ???}
            ?

            ???InternetAddr.sin_family?
            = ?AF_INET;
            ???InternetAddr.sin_addr.s_addr?
            = ?htonl(INADDR_ANY);
            ???InternetAddr.sin_port?
            = ?htons(PORT);

            ???
            if ?(bind(Listen,?(PSOCKADDR)? & InternetAddr,? sizeof (InternetAddr))? == ?SOCKET_ERROR)
            ???
            {
            ??????printf(
            " bind()?failed?with?error?%d\n " ,?WSAGetLastError());
            ??????
            return ;
            ???}



            ???
            if ?(listen(Listen,? 5 )? == ?SOCKET_ERROR)
            ???
            {
            ??????printf(
            " listen()?failed?with?error?%d\n " ,?WSAGetLastError());
            ??????
            return ;
            ???}


            ???
            // 開始接收從客戶端來的連接

            ???
            while (TRUE)
            ???
            {
            ??????
            if ?((Accept? = ?WSAAccept(Listen,?NULL,?NULL,?NULL,? 0 ))? == ?SOCKET_ERROR)
            ??????
            {
            ?????????printf(
            " WSAAccept()?failed?with?error?%d\n " ,?WSAGetLastError());
            ?????????
            return ;
            ??????}


            ??????
            // ?創建一個關鍵項用于保存這個客戶端的信息,用戶接收發送的重疊結構,
            ??????
            // ?還有使用到的緩沖區
            ?????? if ?((PerHandleData? = ?(LPPER_HANDLE_DATA)?GlobalAlloc(GPTR,?
            ?????????
            sizeof (PER_HANDLE_DATA)))? == ?NULL)
            ??????
            {
            ?????????printf(
            " GlobalAlloc()?failed?with?error?%d\n " ,?GetLastError());
            ?????????
            return ;
            ??????}


            ??????
            // ?Associate?the?accepted?socket?with?the?original?completion?port.

            ??????printf(
            " Socket?number?%d?connected\n " ,?Accept);
            ??????PerHandleData
            -> Socket? = ?Accept;

            ??????
            // 與我們的創建的那個完成端口關聯起來,將關鍵項也與指定的一個完成端口關聯
            ?????? if ?(CreateIoCompletionPort((HANDLE)?Accept,?CompletionPort,?(DWORD)?PerHandleData,
            ?????????
            0 )? == ?NULL)
            ??????
            {
            ?????????printf(
            " CreateIoCompletionPort?failed?with?error?%d\n " ,?GetLastError());
            ?????????
            return ;
            ??????}


            ??????
            // ?投遞一次接收,由于接收都需要使用這個函數來投遞一個接收的準備

            ??????
            if ?((PerIoData? = ?(LPPER_IO_OPERATION_DATA)?GlobalAlloc(GPTR,?????????? sizeof (PER_IO_OPERATION_DATA)))? == ?NULL)
            ??????
            {
            ?????????printf(
            " GlobalAlloc()?failed?with?error?%d\n " ,?GetLastError());
            ?????????
            return ;
            ??????}


            ??????ZeroMemory(
            & (PerIoData -> Overlapped),? sizeof (OVERLAPPED));
            ??????PerIoData
            -> BytesSEND? = ? 0 ;
            ??????PerIoData
            -> BytesRECV? = ? 0 ;
            ??????PerIoData
            -> DataBuf.len? = ?DATA_BUFSIZE;
            ??????PerIoData
            -> DataBuf.buf? = ?PerIoData -> Buffer;

            ??????Flags?
            = ? 0 ;
            ??????
            if ?(WSARecv(Accept,? & (PerIoData -> DataBuf),? 1 ,? & RecvBytes,? & Flags,
            ?????????
            & (PerIoData -> Overlapped),?NULL)? == ?SOCKET_ERROR)
            ??????
            {
            ?????????
            if ?(WSAGetLastError()? != ?ERROR_IO_PENDING)
            ?????????
            {
            ????????????printf(
            " WSARecv()?failed?with?error?%d\n " ,?WSAGetLastError());
            ????????????
            return ;
            ?????????}

            ??????}

            ???}

            }

            // 工作線程
            DWORD?WINAPI?ServerWorkerThread(LPVOID?CompletionPortID)
            {
            ???HANDLE?CompletionPort?
            = ?(HANDLE)?CompletionPortID;
            ???DWORD?BytesTransferred;
            ???LPOVERLAPPED?Overlapped;
            ???LPPER_HANDLE_DATA?PerHandleData;
            ???LPPER_IO_OPERATION_DATA?PerIoData;
            ???DWORD?SendBytes,?RecvBytes;
            ???DWORD?Flags;
            ???
            ???
            while (TRUE)
            ???
            {
            ??????
            // 完成端口有消息來了
            ?????? if ?(GetQueuedCompletionStatus(CompletionPort,? & BytesTransferred,
            ?????????(LPDWORD)
            & PerHandleData,?(LPOVERLAPPED? * )? & PerIoData,?INFINITE)? == ? 0 )
            ??????
            {
            ?????????printf(
            " GetQueuedCompletionStatus?failed?with?error?%d\n " ,?GetLastError());
            ?????????
            return ? 0 ;
            ??????}



            ??????
            // 是不是有人退出了

            ??????
            if ?(BytesTransferred? == ? 0 )
            ??????
            {
            ?????????printf(
            " Closing?socket?%d\n " ,?PerHandleData -> Socket);

            ?????????
            if ?(closesocket(PerHandleData -> Socket)? == ?SOCKET_ERROR)
            ?????????
            {
            ????????????printf(
            " closesocket()?failed?with?error?%d\n " ,?WSAGetLastError());
            ????????????
            return ? 0 ;
            ?????????}


            ?????????GlobalFree(PerHandleData);
            ?????????GlobalFree(PerIoData);
            ?????????
            continue ;
            ??????}


            ??????
            //

            ??????
            if ?(PerIoData -> BytesRECV? == ? 0 )
            ??????
            {
            ?????????PerIoData
            -> BytesRECV? = ?BytesTransferred;
            ?????????PerIoData
            -> BytesSEND? = ? 0 ;
            ??????}

            ??????
            else
            ??????
            {
            ?????????PerIoData
            -> BytesSEND? += ?BytesTransferred;
            ??????}


            ??????
            if ?(PerIoData -> BytesRECV? > ?PerIoData -> BytesSEND)
            ??????
            {

            ?????????
            // ?Post?another?WSASend()?request.
            ?????????
            // ?Since?WSASend()?is?not?gauranteed?to?send?all?of?the?bytes?requested,
            ?????????
            // ?continue?posting?WSASend()?calls?until?all?received?bytes?are?sent.

            ?????????ZeroMemory(
            & (PerIoData -> Overlapped),? sizeof (OVERLAPPED));

            ?????????PerIoData
            -> DataBuf.buf? = ?PerIoData -> Buffer? + ?PerIoData -> BytesSEND;
            ?????????PerIoData
            -> DataBuf.len? = ?PerIoData -> BytesRECV? - ?PerIoData -> BytesSEND;

            ?????????
            if ?(WSASend(PerHandleData -> Socket,? & (PerIoData -> DataBuf),? 1 ,? & SendBytes,? 0 ,
            ????????????
            & (PerIoData -> Overlapped),?NULL)? == ?SOCKET_ERROR)
            ?????????
            {
            ????????????
            if ?(WSAGetLastError()? != ?ERROR_IO_PENDING)
            ????????????
            {
            ???????????????printf(
            " WSASend()?failed?with?error?%d\n " ,?WSAGetLastError());
            ???????????????
            return ? 0 ;
            ????????????}

            ?????????}

            ??????}

            ??????
            else
            ??????
            {
            ?????????PerIoData
            -> BytesRECV? = ? 0 ;

            ?????????
            // ?Now?that?there?are?no?more?bytes?to?send?post?another?WSARecv()?request.

            ?????????Flags?
            = ? 0 ;
            ?????????ZeroMemory(
            & (PerIoData -> Overlapped),? sizeof (OVERLAPPED));

            ?????????PerIoData
            -> DataBuf.len? = ?DATA_BUFSIZE;
            ?????????PerIoData
            -> DataBuf.buf? = ?PerIoData -> Buffer;

            ?????????
            if ?(WSARecv(PerHandleData -> Socket,? & (PerIoData -> DataBuf),? 1 ,? & RecvBytes,? & Flags,
            ????????????
            & (PerIoData -> Overlapped),?NULL)? == ?SOCKET_ERROR)
            ?????????
            {
            ????????????
            if ?(WSAGetLastError()? != ?ERROR_IO_PENDING)
            ????????????
            {
            ???????????????printf(
            " WSARecv()?failed?with?error?%d\n " ,?WSAGetLastError());
            ???????????????
            return ? 0 ;
            ????????????}

            ?????????}

            ??????}

            ???}

            }

            posted on 2006-07-07 12:03 楊粼波 閱讀(3647) 評論(4)  編輯 收藏 引用 所屬分類: 網絡編程

            評論

            # re: iocp進行SOCKET通信(轉載) 2007-03-12 14:57 lodzio

            http://www.tope-pelose.lavoro-di-piede.info @X@   回復  更多評論   

            # re: iocp進行SOCKET通信(轉載) 2008-03-22 10:30 郝翰霖

            請問大蝦這代碼是如何格式化的?
            如何讓html仍然按C風格顯示?  回復  更多評論   

            # re: iocp進行SOCKET通信(轉載) 2009-12-29 23:32 人生如戲

            您好,我正在學習這方面的知識。。。希望得到更進一步的學習。。。希望得到您的幫助。。如果有可能請您給我發一份代碼到我的郵箱里面吧。注釋不注釋無所謂啦。。。當然有更好啦。。謝謝!x8990253@126.com  回復  更多評論   

            # re: iocp進行SOCKET通信(轉載) 2010-04-09 17:49 圣神之光

            這里的話應該是接收到數據就傳回給客戶端吧?
            請問如果服務器端接收到數據以后需要處理的話線程需要如何處理?
            GetQueuedCompletionStatus接收到的是否是一個完整的數據呢?
            最近正在學習這個,請大蝦賜教
            回復郵箱:jingamesave@163.com
              回復  更多評論   

            国产成人精品综合久久久| 久久亚洲国产精品123区| 精品999久久久久久中文字幕| 国产成人精品久久一区二区三区 | 久久久久久久97| 国产午夜精品理论片久久| 久久久久久精品成人免费图片| 国产亚洲精久久久久久无码| 久久国产视频99电影| 久久久亚洲欧洲日产国码aⅴ| 国产日韩欧美久久| 亚洲国产精品无码久久一线| 久久精品综合一区二区三区| 国产成人精品综合久久久久| 国产精自产拍久久久久久蜜| 久久久无码精品亚洲日韩蜜臀浪潮| 狠狠人妻久久久久久综合| 蜜臀久久99精品久久久久久小说| 国产999精品久久久久久| 久久婷婷五月综合97色| 亚洲精品无码久久毛片| 久久99久久无码毛片一区二区| 久久久噜噜噜久久熟女AA片 | 精品久久久久久久国产潘金莲 | 久久国产成人午夜aⅴ影院| 久久99国产综合精品| 久久人妻AV中文字幕| 伊人久久国产免费观看视频| 精品国产婷婷久久久| 亚洲综合精品香蕉久久网97| 久久ZYZ资源站无码中文动漫| 国产精品乱码久久久久久软件| 精品熟女少妇aⅴ免费久久| 国产精品99久久精品爆乳| 国内精品伊人久久久久AV影院| 久久久久av无码免费网| 亚洲国产精品嫩草影院久久| 久久久久国产精品三级网| 久久93精品国产91久久综合| 国产无套内射久久久国产| 久久婷婷国产麻豆91天堂|