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

            小明思考

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

            多進程服務端實現-共享socket

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


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

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

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

            可以改進的地方
            1) 使用動態進程池來程序具有更大的伸縮性
            2)監控子進程的狀態,處理僵死進程

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

            父進程(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;
            }

             

            子進程(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: 多進程服務端實現-共享socket[未登錄]  回復  更多評論   

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

            # re: 多進程服務端實現-共享socket  回復  更多評論   

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

            # re: 多進程服務端實現-共享socket[未登錄]  回復  更多評論   

            2009-05-03 16:43 by sun
            hProcess[i] = piProcess[i].hProcess;
            piProcess[i].hProcess狀態改變,hProcess[i]狀態也改變?
            仍沒弄明白
            久久精品一本到99热免费| 99久久亚洲综合精品成人| 久久精品综合网| 囯产极品美女高潮无套久久久| 思思久久精品在热线热| 亚洲色大成网站WWW久久九九| 亚洲欧美成人综合久久久 | 香港aa三级久久三级| 国产午夜精品理论片久久| 久久91精品国产91久| 日产精品久久久久久久| 精品久久国产一区二区三区香蕉| 久久久久久国产精品美女| 国产精品丝袜久久久久久不卡 | 韩国三级中文字幕hd久久精品| 亚洲欧洲精品成人久久奇米网| 国产精品九九九久久九九| 久久91精品国产91久| 久久精品无码免费不卡| 久久国产高潮流白浆免费观看| 亚洲婷婷国产精品电影人久久| 久久精品国产99国产精偷 | 午夜精品久久久久久毛片| 青青青青久久精品国产h| 久久这里只精品99re66| 久久93精品国产91久久综合| AV色综合久久天堂AV色综合在| 久久精品国产日本波多野结衣| 国产精品久久久久久久午夜片| 久久成人国产精品| 久久精品国产AV一区二区三区| 久久93精品国产91久久综合| 久久精品国产亚洲麻豆| 国产精品欧美久久久天天影视| 亚洲伊人久久精品影院| 亚洲中文字幕无码久久2020| 久久精品国产男包| 亚洲中文久久精品无码| 久久综合狠狠综合久久| 99久久精品午夜一区二区| 国产精品美女久久久m|