• <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ù)器端計(jì)算
            posts - 70, comments - 428, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理


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

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

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

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

            下面是一個(gè)echo server 的例子來展示這項(xiàng)技術(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ù)端實(shí)現(xiàn)-共享socket[未登錄]  回復(fù)  更多評論   

            2008-03-10 14:42 by cppexplore
            “這里,我提出另外一種比較獨(dú)特的做法,就是......”
            呵呵,兄弟啊,我畢業(yè)答辯的時(shí)候,老師就反復(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ù)派生線程的方式。
            另可以,起多個(gè)多線程的程序,bind不同port,前端部署lvs提供均衡負(fù)載一樣可以達(dá)到更好的多進(jìn)程效果。

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

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

            # re: 多進(jìn)程服務(wù)端實(shí)現(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)也改變?
            仍沒弄明白
            欧美久久一级内射wwwwww.| 国产精品美女久久久久网| 亚洲国产成人精品91久久久| 国产真实乱对白精彩久久| 超级碰碰碰碰97久久久久| 久久婷婷成人综合色综合| 日韩精品国产自在久久现线拍 | 欧美大战日韩91综合一区婷婷久久青草 | 99精品伊人久久久大香线蕉| 久久人搡人人玩人妻精品首页| 久久久午夜精品福利内容| 久久久久99精品成人片欧美| 国产精品伦理久久久久久| 欧美伊人久久大香线蕉综合| 久久综合狠狠色综合伊人| 日韩中文久久| 国产综合成人久久大片91| 久久精品国产网红主播| 久久综合久久综合亚洲| 亚洲午夜久久影院| 久久综合给合久久狠狠狠97色69| 久久精品国产亚洲精品| 97久久超碰成人精品网站| 国产精品久久久久免费a∨| 精品久久久久中文字| 国产午夜免费高清久久影院| 久久天天躁夜夜躁狠狠| 欧美精品福利视频一区二区三区久久久精品 | 97超级碰碰碰碰久久久久| 亚洲午夜久久久影院| 日韩亚洲国产综合久久久| 国产精品成人久久久久久久| 精品久久777| 国产亚洲婷婷香蕉久久精品| 国产精品一区二区久久国产| 久久经典免费视频| 久久国产精品免费一区二区三区| 996久久国产精品线观看| 香蕉久久夜色精品升级完成| 亚洲国产精品18久久久久久| 亚洲va久久久噜噜噜久久男同|