• <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)也改變?
            仍沒弄明白
            a高清免费毛片久久| 欧美久久一区二区三区| 成人国内精品久久久久一区| 久久99国产精品二区不卡| 久久久久久久亚洲精品| 人妻无码αv中文字幕久久琪琪布 人妻无码久久一区二区三区免费 人妻无码中文久久久久专区 | 性做久久久久久久久久久| 久久久无码精品亚洲日韩蜜臀浪潮| AV无码久久久久不卡蜜桃| 国内精品久久久久久99蜜桃 | 久久久久亚洲AV综合波多野结衣 | 国产精品欧美亚洲韩国日本久久| 天堂无码久久综合东京热| 久久精品九九亚洲精品天堂 | 久久综合久久美利坚合众国| 久久精品成人免费网站| 精品久久久无码21p发布| 国产亚州精品女人久久久久久 | 日本免费久久久久久久网站| 久久精品国产2020| 伊人久久亚洲综合影院| 久久精品亚洲福利| 亚洲天堂久久精品| 99久久亚洲综合精品网站| 国产美女久久久| 99久久超碰中文字幕伊人| 亚洲精品无码久久久久sm| 久久99久久99精品免视看动漫| 亚洲国产日韩欧美久久| 一本色综合久久| 伊人色综合九久久天天蜜桃| 亚洲欧美一级久久精品| 亚洲?V乱码久久精品蜜桃| 伊人伊成久久人综合网777| 亚洲人成电影网站久久| 久久只有这里有精品4| 亚洲精品国精品久久99热| 超级97碰碰碰碰久久久久最新| 久久人人爽人人爽人人片AV东京热 | 久久婷婷色香五月综合激情| 久久亚洲精品无码VA大香大香|