基于嵌入式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;
        }