• <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 小明 閱讀(11221) 評論(3)  編輯 收藏 引用 所屬分類: Win32Network/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的方式嘛。
            并且書中說明這種問題有驚群問題,可以前面加文件鎖或者線程鎖互斥,你文中加的是互斥鎖?,F在的linux從2.2.9版本起就不存在驚群問題而不需要加鎖了,更好的是2.6內核的線程庫中線程鎖不陷入互斥狀態的話就不會陷入內核態了,加不加性能一樣。而win就沒有這么好的線程鎖。
            多進程方式編程簡單,程序健壯性相對比較好,但是切換開銷比較大。現在的更傾向于預派生線程的方式。
            另可以,起多個多線程的程序,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]狀態也改變?
            仍沒弄明白
            久久精品国产精品亚洲艾草网美妙| 成人妇女免费播放久久久| 伊人久久国产免费观看视频| 久久人妻少妇嫩草AV蜜桃| 色综合久久综合中文综合网| 91精品国产综合久久精品| 精品久久久久久国产免费了| 蜜桃麻豆WWW久久囤产精品| 国内精品久久久久影院免费| 久久天天日天天操综合伊人av| 精品国产青草久久久久福利| 久久综合久久综合九色| 久久精品国产99国产精品亚洲 | 国产伊人久久| 亚洲精品国产字幕久久不卡| 久久成人18免费网站| 狠狠色婷婷久久一区二区三区| 精品久久人人爽天天玩人人妻| 亚洲中文字幕无码久久2017| 免费一级做a爰片久久毛片潮| 亚洲∧v久久久无码精品| 深夜久久AAAAA级毛片免费看| 2020久久精品国产免费| 99久久做夜夜爱天天做精品| 国产精品内射久久久久欢欢| 激情伊人五月天久久综合| 亚洲精品乱码久久久久久久久久久久| 久久91精品综合国产首页| 久久久青草久久久青草| 99热成人精品热久久669| 久久久精品人妻一区二区三区四| 久久无码中文字幕东京热| 亚洲午夜无码久久久久小说| 久久乐国产精品亚洲综合| 久久久久婷婷| 久久精品国产亚洲av麻豆蜜芽| 一级做a爰片久久毛片免费陪| 一本久久综合亚洲鲁鲁五月天| 色偷偷88欧美精品久久久| 欧美日韩精品久久久久| 国产精品久久久久久五月尺|