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

            網絡服務器軟件開發/中間件開發,關注ACE/ICE/boost

            C++博客 首頁 新隨筆 聯系 聚合 管理
              152 Posts :: 3 Stories :: 172 Comments :: 0 Trackbacks

                    關于echo的簡單server,幾乎多得發指,但大部分都沒有提供類似粘包,定時器,安全退出等開發中的常用機制,換句話說,為了echo而echo,借鑒價值大打折扣,畢竟我們平時的工作不可能這么簡單。這幾天研究了下asio,感覺不錯,boost接納asio后,在服務器開發領域是不是該得到重視呢:),還是貼代碼吧,有注釋
            // asio.cpp : 定義控制臺應用程序的入口點。
            //

            #include 
            "stdafx.h"

            //禁止boost自動鏈接靜態庫
            #define BOOST_ALL_DYN_LINK

            #include 
            <cstdlib>
            #include 
            <iostream>
            #include 
            <boost/bind.hpp>
            #include 
            <boost/asio.hpp>
            #include 
            <boost/lexical_cast.hpp>

            using boost::asio::ip::tcp;

            class session
            {
            public:
                session(boost::asio::io_service
            & io_service)
                    : socket_(io_service),
                    timer_(io_service),
                    exit_flag_(
            false)        
                
            {
                    std::cout 
            << "session born\n";
                }

                
            ~session()
                
            {
                    std::cout 
            << "session destroy\n";
                }


                tcp::socket
            & socket()
                
            {
                    
            return socket_;
                }


                
            void start()
                
            {//async_receive,async_read_some
                    /*
                    socket_.async_receive(boost::asio::buffer(data_, max_length),
                        boost::bind(&session::handle_read, this,
                        boost::asio::placeholders::error,
                        boost::asio::placeholders::bytes_transferred));
                        
            */

                    
            //讀到4個字節才返回,可以和上面注釋的sync_receive比較
                    boost::asio::async_read(socket_,
                        boost::asio::buffer(data_, 
            4),
                        boost::bind(
            &session::handle_read, this,
                        boost::asio::placeholders::error,
                        boost::asio::placeholders::bytes_transferred
                        ));
                    
                    size_t cancelcnt 
            = timer_.expires_from_now(boost::posix_time::seconds(10));
                    
            //@return The number of asynchronous operations that were cancelled;第一次啟動定時器
                    std::cout << "timer canceled count is = " << cancelcnt << std::endl;
                    
                    timer_.async_wait(boost::bind(
            &session::handle_timeout,this,
                        boost::asio::placeholders::error));        
                }


            protected:

                
            void handle_read(const boost::system::error_code& error,
                    size_t bytes_transferred)
                
            {//可以考慮復雜應用,如:如何集成數據庫操作等
                    
                    
            if (!error)
                    
            {
                        
            if (bytes_transferred < header_lenght)
                        
            {//處理正常退出
                            std::cout << "need close\n";
                            
            this->handle_exit();
                            delete 
            this;
                            
            return;
                        }

                        
            else if (bytes_transferred == header_lenght)//header
                        {
                            data_[bytes_transferred] 
            = '\0';
                            std::cout 
            << "packet len = " << data_ << std::endl;
                            
            int bodylen = boost::lexical_cast<int>(data_);
                            boost::asio::async_read(socket_,
                                boost::asio::buffer(data_,bodylen),
                                boost::bind(
            &session::handle_read,this,
                                boost::asio::placeholders::error,
                                boost::asio::placeholders::bytes_transferred));    
                            
                            
            return;
                        }

                        
            else
                        
            {//讀到了bodylen長度才返回,如果由于網絡原因等導致長時間沒有讀全,則上面的定時器會做超時處理
                            if (bytes_transferred < max_length)
                            
            {
                                data_[bytes_transferred] 
            = '\0';
                            }

                            std::cout 
            << data_ << std::endl;
                            boost::asio::async_write(socket_,
                                boost::asio::buffer(data_, bytes_transferred),
                                boost::bind(
            &session::handle_write, this,
                                boost::asio::placeholders::error));
                            
            //                 size_t cancelcnt = timer_.expires_from_now(boost::posix_time::seconds(10));
            //                 std::cout << "timer canceled count is = " << cancelcnt << std::endl;
            //                 timer_.async_wait(boost::bind(&session::handle_timeout,this,
            //                      boost::asio::placeholders::error));                
                            socket_.async_receive(boost::asio::buffer(data_, 1),
                                boost::bind(
            &session::handle_read, this,
                                boost::asio::placeholders::error,
                                boost::asio::placeholders::bytes_transferred));
            //發起異步讀操作,以便后面正常退出
                         }
                        
                    }

                    
            else
                    
            {
                        std::cout 
            << "error = " << error << "   bytes_transferred = " << bytes_transferred << std::endl;
                        
            this->handle_exit();
                        delete 
            this;//這句不能放在handle_exit里面,否則問題多多,沒找到好的解決方案
                    }

                }


                
            void handle_write(const boost::system::error_code& error)
                
            {
                    
            if (!error)
                    
            {
                        std::cout 
            << "handle_write ok\n";    
                        
            this->handle_exit();
                    }

                    
            else
                    
            {
                        std::cout 
            << "handle_write error\n";
                    }
                    
                    
            return;
                }

                
            void handle_timeout(const boost::system::error_code& e)
                
            {
                    
            if (e != boost::asio::error::operation_aborted)
                    
            {
                        std::cout 
            << "timeout now.\n";    
                        
            this->handle_exit();
                    }

                    
            else
                    
            {//被取消
                        std::cout << "cancelled now.\n";
                    }
                        
                    
            return;
                }

                
            void handle_exit()
                
            {
                    std::cout 
            << "enter handle_exit1.\n";        
                    
            if (!exit_flag_)
                    
            {
                        std::cout 
            << "enter handle_exit2.\n";
                        exit_flag_ 
            = true;
                        timer_.cancel();
                        socket_.close();
                        std::cout 
            << "after socket close.\n";
                        
            /*
                        Any asynchronous send, receive
                        or connect operations will be cancelled immediately, and will complete
                        with the boost::asio::error::operation_aborted error
                        
            */

                        
            //delete this;
                        return;
                    }

                    
            else
                    
            {
                        
            return;
                    }

                }


            private:
                tcp::socket socket_;    
                boost::asio::deadline_timer timer_;
                
            bool exit_flag_;    
                
            enum {header_lenght = 4,  max_length = 1024 };
                
            char data_[max_length];
            }
            ;

            class server
            {
            public:
                server(boost::asio::io_service
            & io_service, short port)
                    : io_service_(io_service),
                    acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
                
            {
                    session
            * new_session = new session(io_service_);
                    acceptor_.async_accept(new_session
            ->socket(),
                        boost::bind(
            &server::handle_accept, this, new_session,
                        boost::asio::placeholders::error));
                }


                
            void handle_accept(session* new_session,
                    
            const boost::system::error_code& error)
                
            {
                    
            if (!error)
                    
            {
                        new_session
            ->start();
                        new_session 
            = new session(io_service_);
                        acceptor_.async_accept(new_session
            ->socket(),
                            boost::bind(
            &server::handle_accept, this, new_session,
                            boost::asio::placeholders::error));
                    }

                    
            else
                    
            {
                        delete new_session;
                    }

                }


            private:
                boost::asio::io_service
            & io_service_;
                tcp::acceptor acceptor_;
            }
            ;

            int main(int argc, char* argv[])
            {
                
            try
                
            {    
                    boost::asio::io_service io_service;        
                    server s(io_service, 
            9000);

                    io_service.run();
                }

                
            catch (std::exception& e)
                
            {
                    std::cerr 
            << "Exception: " << e.what() << "\n";
                }


                
            return 0;
            }


                  下面是python測試腳本:
                  import socket,sys,time

            host = sys.argv[1]
            strPort = sys.argv[2]
            sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            port = int(strPort)

            try:
                sock.connect((host,port))
            except socket.gaierror,e:
                print "addr error:%s" % e
                sys.exit(1)
               
            except socket.error,e:
                print "connection error :%s" % e
                sys.exit(1)
               
            try:
                pack = 'hello world!'
                packheader = '%04d' % len(pack)
                print "header : %s" % packheader
                sock.sendall(packheader)
                sock.sendall(pack)
                time.sleep(10)
                sock.sendall("hello world from python2!")
                recvbuf = sock.recv(1024)
                print "recv data : %s " % recvbuf
            except socket.error,e:
                print "send data error : %s" % e
                sys.exit(1)
               
            print "exit now"
                  測試腳本中的內容可以靈活修改,用python寫這個實在是方便,比起用C++來寫,強多了。
                  最后,歡迎大家到www.opensourceinsight.com交流哦,呵呵

            posted on 2008-07-20 13:45 true 閱讀(3684) 評論(3)  編輯 收藏 引用 所屬分類: boost 、通信技術

            Feedback

            # re: Asio實現的實用echo server 2008-07-20 19:28 haskell
            python做網絡測試確實不錯
            c++的網絡庫一抓一大把,而且質量都不錯  回復  更多評論
              

            # re: Asio實現的實用echo server 2008-08-21 15:24 roger007
            this->handle_exit();
            delete this;//這句不能放在handle_exit里面,否則問題多多,沒找到好的解決方案

            =============
            可以考慮使用boost的智能指針來解決這個問題,就不需要再考慮對象的delete了,具體可以參考ASIO的chat例子。
              回復  更多評論
              

            # re: Asio實現的實用echo server 2009-05-11 15:19 zxh
            我看了一下asio下的example\http2 其中創建了多個io_service放入多個線程來執行run方法。 與http3這個例子中的多線程有什么區別,其中他使用了strand來同步線程,http2中沒有,我有些不太明白,還有不少疑問想請教一下你, 你加的QQ嗎?我的QQ:6346289  回復  更多評論
              

            国产成人精品久久| 久久AAAA片一区二区| 久久se精品一区二区影院| 亚洲国产精品无码久久久秋霞2 | 日本久久中文字幕| 久久精品国产亚洲AV不卡| 久久AV高潮AV无码AV| 亚洲欧美精品伊人久久| 久久久久久国产精品无码下载 | 亚洲国产一成久久精品国产成人综合 | 久久久国产精品福利免费| 国产精品久久久久影视不卡| 国产日韩欧美久久| 99久久国产免费福利| 丰满少妇人妻久久久久久4| 久久不见久久见免费视频7| 欧美国产成人久久精品| 人妻无码αv中文字幕久久琪琪布| 久久亚洲综合色一区二区三区| 国产精品久久久久久| 久久综合久久综合久久综合| 狠狠综合久久综合中文88| 欧美激情精品久久久久久久| 青草久久久国产线免观| 亚洲精品乱码久久久久久按摩 | 久久久久久久久无码精品亚洲日韩 | 亚洲午夜久久久影院伊人| 久久久久九国产精品| 2021国产精品午夜久久| 欧美粉嫩小泬久久久久久久| 久久婷婷国产综合精品| 91久久国产视频| 久久久久人妻一区二区三区 | 久久人人爽人人爽人人片AV高清| 国产精品乱码久久久久久软件| 波多野结衣AV无码久久一区| 99久久国产亚洲高清观看2024| 亚洲综合久久夜AV | 99久久国产热无码精品免费 | 久久人人爽人人爽人人片av麻烦 | 久久不见久久见免费影院www日本|