? 基于嵌入式Linux的网络终端应用程序设计--技术天地

基于嵌入式Linux的網絡終端應用程序設計

 2010/4/28    

        EM9160具有豐富的通訊接口,可以支持基于以太網和PPP(如GPRS/CDMA)的網絡應用。本文主要介紹EM9160作為TCP客戶端方式的應用示例:Step4_TCPClient。

 

TCP客戶端Socket編程流程

 

        在利用Socket進行TCP客戶端編程時,建立TCP連接的過程一般比較簡單,首先客戶端調用socket()函數建立流式套接字,然后調用connect()函數請求服務器端建立TCP連接,成功建立連接后即可與服務器端進行TCP/IP數據通訊,流程如下:

 

TCP客戶端Socket編程流程

 

TCPClient應用示例

 

        Step4_TCPClient是一個具有自動管理功能的TCP客戶端應用示例。作為TCP客戶端主動和服務器端建立TCP連接的過程編程相對簡單,直接調用相關的Socket函數即可,建立TCP連接的功能封裝在CTCPClient類中。嵌入式的應用場合大多是處于長期運行無人值守的狀態,可能會遇到需要一直保持TCP客戶端連接的情況,Step4_TCPClient例程基于這種需求,專門封裝了一個CTCPClientManager管理類對TCPClient的連接進行自動管理,包括啟動建立TCP的客戶端連接、查詢TCP連接的狀態、添加多個TCP客戶端連接等功能。

 

        CTCPClient類

        CTCPClient類定義在TCPClient.H文件下,該類提供了4個公共函數,以及一個數據通訊線程,調用該類中的相關函數與TCP服務器端建立連接。

 

        class CTCPClient
        {
        private:
                pthread_t m_thread; //通訊線程標識符ID
                //數據通訊處理線程函數
                static int SocketThreadFunc( void*lparam );
        public:
                // TCP通訊Socket
               
int m_sockfd;
                int m_sockclose;
                int m_ExitThreadFlag; 
                //遠程主機IP地址
                char m_remoteHost[255];
                //遠程主機端口
                int m_port;
                char RecvBuf[1500];
                int m_nRecvLen;

        public:
                CTCPClient();
                virtual ~CTCPClient( );
                //打開創建客戶端socket
                int Open( char* ServerIP, int ServerPort );
                //關閉客戶端socket
                int Close( );
                //與服務器端建立連接 并創建數據通訊處理線程
                int Connect();
                //向服務器端發送數據
                int SendData( char * buf , int len);
        };

 

        Open函數執行創建打開socket操作,并設置遠端TCP服務器的IP和端口。

 

        Connect函數調用connect( )與遠端TCP服務器建立連接,調用select( )等待TCP連接的建立,TCP連接建立成功,則創建TCP數據通訊處理線程。

 

        SocketThreadFunc函數是實現TCP連接數據通訊的核心代碼,在該函數中調用select( ),等待TCP連接的通訊數據,對于接收的TCP連接數據的處理也是在該函數中實現,在本例程中處理為簡單的數據回發,用戶可結合實際的應用修改此處代碼。流程如下:

 

TCP客戶端Socket編程流程

 

        CTCPClientManager類

        TCP客戶端連接定義為四個狀態:

        enum CONNSTATE{ csWAIT, csINIT, csCLOSED, csOPEN };其中csOPEN表明TCP客戶端連接建立。

 

        CTCPClientManager所封裝的功能函數就是根據連接的各個狀態對TCP客戶端連接進行管理,CTCPClientManager類定義在TCPClientManager.H文件下。

 

        class CTCPClientManager
        {
        private:
                // TCPClient連接管理線程
                static int TCPClientThreadFunc( void* lparam );
        public:
                TCPCLIENT_INFO m_TCPClientInfo[TCPCLIENT_MAX_NUM];
                pthread_t m_thread[TCPCLIENT
_MAX_NUM];
                int m_nTCPClientNum;
        public:
                CTCPClientManager( );
                ~CTCPClientManager();
                //添加TCP客戶端連接對象,輸入參數為TCP服務器的IP和端口
                int AddTCPClientObject( char* pHostIP, int nHostPort );
                //刪除所有TCP客戶端連接對象
                int DeleteAllTCPClient( );
                //設置TCP客戶端連接對象為csINIT狀態
                int Open( int Idx );
                //獲取TCP客戶端連接狀態
                int GetTCPClientState( int Idx );
                //啟動TCPClient連接管理操作,并創建TCPClient連接管理線程 
                int Start( );
                //關閉TCPClient連接管理操作
                int Stop( );
        };

 

        TCPClientThreadFunc函數是實現對TCP連接狀態管理操作的核心代碼,由于Linux下sleep的最小單位為秒,對于毫秒級的延時等待,在該函數中利用調用select( )設置相關的時間參數來實現。流程如下:

 

TCP客戶端Socket編程流程

 

        CTCPClientManager類的調用

        CTCPClientManager類的具體使用過程:首先調用類中定義AddTCPClientObject加載TCP連接對象,然后調用類中定義Start函數來啟動TCP連接自動管理線程,Open函數將TCP連接狀態設置為csINIT狀態。本例程中主循環的操作為每隔1s查詢TCPClient連接的狀態,如果狀態為csWait,程序調用Open函數將其設置為csINIT狀態,則TCPC連接管理線程將自動進行與TCP服務器端建立連接的操作。

 

        以下為Step4_TCPClient.cpp中的相關代碼。

 

        class CTCPClientManager TCPClntManager;
        int main()
        {
                int i1, i2, i3;
                //添加一個TCP客戶端連接對象
                TCPClntManager.AddTCPClientObject( '192.168.201.121', 1001 );
                //啟動TCPClient連接管理操作,并創建TCPClient連接管理線程
                TCPClntManager.Start();
                for( i1=0; i1                {
                        //設置TCP客戶端連接初始狀態,連接管理線程將自動進行TCP的連接操作
                
        TCPClntManager.Open(i1);
                }
                for(i1=0; i1<10000; i1++)
                {
                        sleep(1);
                        for( i2=0; i2                        {
                                // 查詢TCP客戶端連接狀態
                                i3 = TCPClntManager.GetTCPClientState(i2);
                                printf( 'TCP Connect%d State: %d \n', i2+1, i3 );
                                if( i3==0 ) 
                                {
                                        //設置TCP客戶端連接初始狀態,連接管理線程將自動進行TCP連接操作
                                       
TCPClntManager.Open( i2 );
                                }
                        } 
                }
                return 0;
        }