• <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>

            小明思考

            高性能服務(wù)器端計算
            posts - 70, comments - 428, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            多進(jìn)程服務(wù)端實現(xiàn)-共享socket

            Posted on 2008-03-10 14:09 小明 閱讀(11226) 評論(3)  編輯 收藏 引用 所屬分類: Win32Network/ACE


            眾所周知,使用多進(jìn)程的服務(wù)端模型有利于程序的健壯性。傳統(tǒng)的做法是主進(jìn)程負(fù)責(zé)收發(fā)數(shù)據(jù),然后傳給子進(jìn)程來處理。這種做法的缺陷是需要大量的父子進(jìn)程IPC,對效率來說是一種損失。

            這里,我提出另外一種比較獨特的做法,就是多個進(jìn)程share socket,每次進(jìn)程都可以accept,然后來自己處理。

            幾個關(guān)鍵點:
            1) CreateProcess使用InheritHandle標(biāo)記來share socket handle
            2) 通過command line直接向子進(jìn)程來傳遞父socket的值
            3)使用Global Mutext來實現(xiàn)子進(jìn)程互斥的accept

            可以改進(jìn)的地方
            1) 使用動態(tài)進(jìn)程池來程序具有更大的伸縮性
            2)監(jiān)控子進(jìn)程的狀態(tài),處理僵死進(jìn)程

            下面是一個echo server 的例子來展示這項技術(shù), FYI

            父進(jìn)程(SSParent.cpp)

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

            #define MUTEX_NAME "sschild"

            int main(int argc, char* argv[])
            {
                { 
            //init
                    WORD wVersionRequested;
                    WSADATA wsaData;
                    wVersionRequested 
            = MAKEWORD( 22 );
                    WSAStartup( wVersionRequested, 
            &wsaData );
                }

                SOCKET s 
            = socket(AF_INET,SOCK_STREAM,0);
                
            if(s==INVALID_SOCKET)
                {
                    printf(
            "create socket failed!\n");
                    
            return -1;
                }

                { 
            //bind&listen
                    sockaddr_in sa;
                    sa.sin_family 
            = AF_INET;
                    sa.sin_port 
            = htons( 1500 );
                    sa.sin_addr.s_addr 
            = 0 ; 
                    
            int rc = bind(s,(sockaddr *)&sa,sizeof(sa));
                    
            if(rc == SOCKET_ERROR)
                    {
                        printf(
            "bind failed:%d\n",::WSAGetLastError());
                        
            return -1;
                    }
                    listen(s,SOMAXCONN);
                }

                HANDLE hSocketMutex;
                { 
            //create mutex
                    hSocketMutex = ::CreateMutex(NULL,FALSE,MUTEX_NAME);
                    
            if(hSocketMutex==NULL)
                    {
                        printf(
            "fail CreateMutex:%d\n",::GetLastError());
                        
            return -1;
                    }
                }

                
            const int CHILD_NUMBER = 5;
                HANDLE hProcess[CHILD_NUMBER];
                { 
            //create child process
                   STARTUPINFO si = { sizeof(si) };
                   PROCESS_INFORMATION piProcess[CHILD_NUMBER];
                   
            char pCmdLine[256];
                   sprintf(pCmdLine,
            "SSChild %d",s);
                   
            for(int i=0;i<CHILD_NUMBER;++i)
                   {
                       
            if(!CreateProcess(NULL,pCmdLine,NULL,NULL,TRUE,0, NULL, NULL, &si, &piProcess[i]))
                       {
                           printf(
            "fail CreateProcess:%d\n",::GetLastError());
                           
            return -1;
                       }
                       hProcess[i] 
            = piProcess[i].hProcess;
                       CloseHandle(piProcess[i].hThread);
                   }
                }

                ::WaitForMultipleObjects(CHILD_NUMBER,hProcess,TRUE,INFINITE);

                {
            //close all child handle
                   for(int i=0;i<CHILD_NUMBER;++i)
                   {
                       CloseHandle(hProcess[i]);
                   }
                }

                
            //clean
                CloseHandle(hSocketMutex);
                closesocket(s);
                WSACleanup( );
                
            return 0;
            }

             

            子進(jìn)程(SSChild.cpp)

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

            #define MUTEX_NAME "sschild"

            int main(int argc, char* argv[])
            {
                printf(
            "sschild startup!\n");

                { 
            //init
                    WORD wVersionRequested;
                    WSADATA wsaData;
                    wVersionRequested 
            = MAKEWORD( 22 );
                    WSAStartup( wVersionRequested, 
            &wsaData );
                }

                DWORD pid 
            = ::GetCurrentProcessId();

                HANDLE hSocketMutex;
                { 
            //open mutex
                    hSocketMutex = ::OpenMutex(MUTEX_ALL_ACCESS,FALSE,MUTEX_NAME);
                    
            if(hSocketMutex==NULL)
                    {
                        printf(
            "fail OpenMutex:%d\n",::GetLastError());
                        
            return -1;
                    }
                }

                SOCKET s;
                {  
            //get socket handle from cmdline
                    if(argc<=1)
                    {
                        printf(
            "usage: sschild socket_handle\n");
                        
            return -1;
                    }
                    s 
            = (SOCKET) atoi(argv[1]);
                }

                
            while(1)
                {
                    WaitForSingleObject(hSocketMutex,INFINITE);
                    sockaddr_in sa;
                    
            int add_len = sizeof(sa);
                    SOCKET c 
            = accept(s,(sockaddr*)&sa,&add_len);
                    ReleaseMutex(hSocketMutex);
                    
            if(c!=INVALID_SOCKET)
                    {
                        printf(
            "[%d],client:%s port:%d connected!\n",pid,inet_ntoa(sa.sin_addr),sa.sin_port);
                        
            while(1)
                        {
                            
            char buffer[256]={0};
                            
            int rc= recv(c,buffer,255,0);
                            
            if(rc>0)
                            {
                                printf(
            "[%d]recv msg:%s\n",pid,buffer);
                                send(c,buffer,strlen(buffer)
            +1,0);
                            }
                            
            else if(rc == SOCKET_ERROR)
                            {
                                printf(
            "[%d]recv msg failed:%d\n",pid,::WSAGetLastError());
                                closesocket(c);
                                
            break;
                            }
                            
            else
                            {
                                printf(
            "[%d]connection close\n",pid);
                                closesocket(c);
                                
            break;
                            }
                        }
                    }
                    
            else
                    {
                        printf(
            "[%d]fail accept:%d\n",pid,::WSAGetLastError());
                    }
                }

                CloseHandle(hSocketMutex);
                
            return 0;
            }

            Feedback

            # re: 多進(jìn)程服務(wù)端實現(xiàn)-共享socket[未登錄]  回復(fù)  更多評論   

            2008-03-10 14:42 by cppexplore
            “這里,我提出另外一種比較獨特的做法,就是......”
            呵呵,兄弟啊,我畢業(yè)答辯的時候,老師就反復(fù)的批評我們,“我提出.......”,“我發(fā)明......”之類的東西。
            文中就是《unix網(wǎng)絡(luò)編程》中的預(yù)派生進(jìn)程阻塞在accept的方式嘛。
            并且書中說明這種問題有驚群問題,可以前面加文件鎖或者線程鎖互斥,你文中加的是互斥鎖。現(xiàn)在的linux從2.2.9版本起就不存在驚群問題而不需要加鎖了,更好的是2.6內(nèi)核的線程庫中線程鎖不陷入互斥狀態(tài)的話就不會陷入內(nèi)核態(tài)了,加不加性能一樣。而win就沒有這么好的線程鎖。
            多進(jìn)程方式編程簡單,程序健壯性相對比較好,但是切換開銷比較大。現(xiàn)在的更傾向于預(yù)派生線程的方式。
            另可以,起多個多線程的程序,bind不同port,前端部署lvs提供均衡負(fù)載一樣可以達(dá)到更好的多進(jìn)程效果。

            # re: 多進(jìn)程服務(wù)端實現(xiàn)-共享socket  回復(fù)  更多評論   

            2008-07-06 02:12 by 放屁啊狗
            windows的socket只能說是個小玩藝兒,跟unix下的socket簡直無法比擬,可見windows只能做desktop系統(tǒng)

            # re: 多進(jìn)程服務(wù)端實現(xiàn)-共享socket[未登錄]  回復(fù)  更多評論   

            2009-05-03 16:43 by sun
            hProcess[i] = piProcess[i].hProcess;
            piProcess[i].hProcess狀態(tài)改變,hProcess[i]狀態(tài)也改變?
            仍沒弄明白
            国产午夜精品理论片久久影视 | 韩国三级中文字幕hd久久精品| 久久精品人人做人人爽97| 久久综合狠狠综合久久| 9久久9久久精品| 久久亚洲精品无码观看不卡| 一本一本久久aa综合精品| 久久亚洲AV成人出白浆无码国产| 国产一级持黄大片99久久| 久久se精品一区二区影院| 亚洲午夜久久久影院| 久久精品男人影院| 久久久久青草线蕉综合超碰| 久久国产免费观看精品| 香蕉久久夜色精品国产尤物| 国产精品美女久久久久久2018| 久久乐国产精品亚洲综合| 国产日产久久高清欧美一区| 国内精品伊人久久久久妇| 日韩亚洲欧美久久久www综合网| 伊人久久亚洲综合影院| 99久久亚洲综合精品成人| 99久久精品免费看国产一区二区三区 | 久久91精品国产91久| 国产精品久久久久久久久免费| 久久妇女高潮几次MBA| 国产69精品久久久久9999APGF| 日韩精品久久久久久久电影蜜臀| 久久综合狠狠综合久久97色| 久久99国产精品尤物| 香蕉久久夜色精品升级完成| 亚洲AV伊人久久青青草原| 成人a毛片久久免费播放| 国产欧美久久久精品| 久久久av波多野一区二区| 伊人色综合久久天天人手人婷| 久久狠狠一本精品综合网| 久久成人18免费网站| 久久人人爽人人爽人人片AV东京热 | 国内精品久久久久久久涩爱| 精品久久一区二区|