字节型TCP协议解析

#include <stdio.h>  
#include <stdlib.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <sys/un.h>  
#include <unistd.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>
#include <error.h>
#include <errno.h>
#include <string>
#include <list>


#define DEBUGS  


inline char* memstr(void *buf , int size  , void * need , int needsize)
{
    char *p=(char*) buf;
    int index = 0 ;
    while(index < size)
    {
        if((size-index) < needsize )
        {
            return NULL;
        }
        if( memcmp(p,need,needsize) == 0 ) //find the right buffer(need)
        {
        //  printf("find,index=%d\n",index);
            return p;
        }
        else
        {
            ++p;
            index++;
        }
    }
    return NULL;
}


class BaseHandler
{
    public:
    BaseHandler()
    {}
    virtual ~BaseHandler()
    {}
    public:
    virtual int hander( void * data ,  int size ) =0;
    void config(const char *p )
    {
        strFileName= p;
    }
    protected :
    std::string strFileName ; 
};

class MagReader :public BaseHandler
{
    public:
    typedef struct _msg_data_
    {
        void *p;
        int size ; 
        _msg_data_( void * a , int b )
        {
            p =malloc(b);
            memcpy(p , a , b ) ; 
            size = b ; 
        }
        ~_msg_data_()
        {
            if(p)
            free(p);
        }
    }MSG,*P_MSG;
    public:
    MagReader()
    {}
    ~MagReader()
    {
        for( std::list<P_MSG>::iterator it =m_list.begin() ; it!=m_list.end() ;it++ )
        {
            delete (*it) ; 
        }
    }
    public:
    int hander( void * data ,  int size )
    {
        P_MSG buf =  new MSG( data ,size ) ; 
        m_list.push_back(buf);

#ifdef DEBUGS   
        char *p_=(char*)data ; 
        for( int  i = 0 ; i < size ; i++)
        {
            printf("%c" , p_[i]) ;
        }
        printf("\n") ; 
#endif
    }
    private:
    std::list<P_MSG> m_list ; 
};

class FileWriter:public BaseHandler
{
    public:
    FileWriter():fp(NULL) , bopened(false)
    {

    }
    ~FileWriter()
    {
        if(fp)
        {
            fclose(fp) ;
            fp = NULL ;
            bopened = false ; 
        }
    }
    public:
    int hander( void * data ,  int size  ) 
    {
         if(bopened)
         {
             this->write(data, size ) ;
         }
         else
         {
             this->open(strFileName.c_str() ) ; 
             this->write(data, size ) ;
         }
    }
    public:
    const int open(const char * filename)
    {
        fp=fopen(filename,"w+") ;
        bopened=true;
    }
    const int write( void * buffer  , int buffer_size = 1 )
    {
            fwrite(buffer , buffer_size , 1 ,fp ) ; 
            return 0;
    }
    private:
    FILE *fp;
    bool bopened; 
};

class Factory
{
    public:
    static BaseHandler* object( int type )
    {
        switch(type)
        {
            case 0:
            return new MagReader();
            break;
            case 1:
            return new FileWriter();
            break;
            default:
            break;
        }
        return NULL ;
    }
};

typedef int socket_t ;
class FileTransport
{
    private:
    FileTransport();
    ~FileTransport();
    public:
    static FileTransport* instance();
    static void release() ;
    public:
    const int Init( char *ServerIP,  int Serverport ) ;
    const int OpenCusor( char *mesh , char*sql) ; 
    const int Fetch( ) ;
    const int Fetch2( ) ;
    const int Fetch3( ) ;
    void Close() ;
    void setfile(const char * p) ; 
    private:
    socket_t fd ;
    static FileTransport* m_pFileTransport ; 
    BaseHandler* handler;
    std::string strFileName ; 
} ;

FileTransport* FileTransport::m_pFileTransport=NULL;
FileTransport::FileTransport()
{
    fd = socket(AF_INET,SOCK_STREAM,0);
    handler = NULL ;
}

FileTransport::~FileTransport()
{
    this->Close() ; 
    if(handler)
    {
        delete handler;
        handler=NULL;
    }
}
void FileTransport::setfile(const char * p) 
{
    strFileName=p;
}

FileTransport* FileTransport::instance()
{
    if(m_pFileTransport == NULL )
    {
        m_pFileTransport=new FileTransport();
    }
    return m_pFileTransport;
}

void FileTransport::release()
{
    if(m_pFileTransport)
    {
        delete m_pFileTransport ; 
    }
}

//连接服务器
const int FileTransport::Init( char *ServerIP,  int Serverport ) 
{
    struct sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = inet_addr(ServerIP);  
    address.sin_port = htons(Serverport);  
    int uiLen = sizeof(address); 
    int ret = connect( fd ,(struct sockaddr *)&address,uiLen );
    if(ret != 0 )
    {
        printf("connect failed") ; 
        return -1;
    }
}
void FileTransport::Close() 
{
    ::close(fd);
}
 const int FileTransport::OpenCusor( char *mesh , char*sql) 
 {
    char ch[1024] = {0};
    char *p = ch ;
    strcpy( p, mesh ) ; 
    p+= strlen(mesh) ; 

    strcpy( p," " ) ;
    p+= 1 ; 
    strcpy( p,sql ) ;
    int idatasize = strlen(ch);
    printf("data is [%s],size=%d\n",ch,idatasize ) ; 
    ::send(fd,&idatasize,sizeof(int) , 0 ) ; 
    ::send(fd,ch,idatasize ,0);


    char chm ={0};
    ::recv( fd , &chm , 1 , 0   ) ;
    printf("chm=%d\n" , chm ) ; 
 }

//provide a method to prevent tcp pollution.
//the process hanged up to  wait the timing when the Protocol_Header  is found in the 
// recv tcp streams . 
// in anthor words , if the process is waked up , means that recv the right character 
//we wanted . by the way , continue to handler the next stream is allowed .  
#if 1
const int FileTransport::Fetch3( ) 
{
#define Protocol_Header 0xFDF4
#define Protocol_Tail 0xFDF5
#define ReadIOCacheSize 2   
/***不需要字节对齐***/
    #pragma pack(1)
    struct headers
    {
        //unsigned int a ; 
        unsigned short head ; 
        unsigned char type;
        unsigned int length;
    };
    #pragma pack()

    #pragma pack(1)
    struct tail
    {
        unsigned char check;
        unsigned short tail;
    };
    #pragma pack()

    struct headers obj ; 
    memset(&obj,  0x00 ,sizeof(obj) ) ; 
    char *pHead=(char*)malloc( obj.head)   ;
    char *pHead_Walk = pHead ;
    char *pHead_End = pHead_Walk+(sizeof(obj.head) -1 ) ; 
    while(1)
    {
        unsigned char ch;
        ::recv(fd,&ch,1,0 ) ; 
        if( pHead_Walk <   pHead_End ) 
        {
            memcpy(pHead_Walk , &ch , 1 )  ;
            ++pHead_Walk;
        }
        else// equal
        {
            memcpy(pHead_Walk , &ch , 1 )  ;
            unsigned short s = 0 ;
            memcpy(&s , pHead , sizeof(s) ) ;
            if( s == Protocol_Header )//find the right character position
            {
                obj.head = s ; 
                break;
            }
            else
            {
                pHead_Walk=pHead;
            }

        }
    }
    if(pHead)
    {
        free(pHead) ; 
    }
    printf("start get type and length\n");
    char *pBuf = (char*)(&obj) ; 
    pBuf += sizeof(obj.head) ;//skip the head 
    char *pBuf_Walk = pBuf ; 

    int iReadHead_Reset = 0 ; 
    while(iReadHead_Reset<(sizeof(obj) - sizeof(obj.head)  ))
    {
        char chBuf[ 1024 ] ={0} ;  
        int size = ::recv(fd,chBuf, ( sizeof(obj) - sizeof(obj.head) ) ,0 )  ; 
        memcpy(pBuf_Walk ,chBuf ,size  ) ; 
        pBuf_Walk += size ; 
        iReadHead_Reset+=size ; 
    }
    printf("type=%d,   length=%d\n" , obj.type, obj.length ) ; 




    handler = Factory::object(obj.type) ;
    if(!handler)
    {
        printf("tyep[%d] is error\n" , obj.type )  ;
        return -1; 
    }
    handler->config(strFileName.c_str());




    char buf[ReadIOCacheSize]={0};
    int bufreaded = 0 ; 
    /*查找匹配的正文.每次读取当前剩余的字节数与ReadIOCacheSize的最小值*/
    do
    {
        int sizeEach=(ReadIOCacheSize>( obj.length -bufreaded ) )?( ( obj.length -bufreaded ) ):(ReadIOCacheSize);
        memset(buf,0x00 ,sizeof(buf) ) ; 
        int ret = recv( fd , buf , sizeEach , 0   ) ; 
        #ifdef WIN32 
        if(ret == SOCKET_ERROR)
        {
            return -1;
        }
        #else
        if(ret == EAGAIN)
        {
            return -1;
        }   
        #endif
        bufreaded+=ret;

        handler->hander(buf ,ret ) ; 
        printf("[%d receieved]%s\n",ret,buf) ; 
    }while(bufreaded < obj.length  ) ; 


    //检查包的结尾
    struct tail otail;
    memset( &otail , 0x00 , sizeof(otail) ) ;
    char *ptail = (char*)&otail ; 
    char *otail_Walk  = ptail ; 
    int inReadTail  =  0  ; 
    while( inReadTail < sizeof(otail) )
    {
        char tmp[sizeof(otail) ] = {0} ;
        int ret = ::recv(fd,tmp,sizeof(otail),0);
        #ifdef WIN32 
        if(ret == SOCKET_ERROR)
        {
            return -1;
        }
        #else
        if(ret == EAGAIN)
        {
            return -1;
        }   
        #endif
        memcpy(otail_Walk,tmp ,ret  ) ; 
        inReadTail+=ret;
        otail_Walk+=ret;
    }


    #if  0 
    char tmp[1024] = {0} ; 
    while(1)
    {
        memset(tmp,0x00 , sizeof(tmp) ) ; 
        int ret = ::recv(fd,tmp,sizeof(otail),0);
        #ifdef WIN32 
        if(ret == SOCKET_ERROR)
        {
            return -1;
        }
        #else
        if(ret == EAGAIN)
        {
            return -1;
        }   
        #endif
        if(ret ==  sizeof(otail))
        {
            break ; 
        }
        else
        {
            continue  ; 
        }
    }

    memcpy(&otail , tmp , sizeof(otail)  ) ;
    #endif

    printf("tail=%d\n" , otail.tail) ; 
    if( otail.tail != Protocol_Tail )
    {
        printf("receive error tail[%d]\n" ,otail.tail ) ; 
        sleep(10000) ; 
        return -1;
    }

    return 0; 
    //.........
}
#endif

const int FileTransport::Fetch2( ) 
{
#define Protocol_Header 0xFDF4
#define Protocol_Tail 0xFDF5
#define ReadIOCacheSize 2   
/***不需要字节对齐***/
    #pragma pack(1)
    struct headers
    {
        //unsigned int a ; 
        unsigned short head ; 
        unsigned char type;
        unsigned int length;
    };
    #pragma pack()

    #pragma pack(1)
    struct tail
    {
        unsigned char check;
        unsigned short tail;
    };
    #pragma pack()


/*查找匹配的头*/
    struct headers oheaders;
    memset(&oheaders,0x00,sizeof(oheaders) ) ;  
    printf("sizeof struct headers = %d\n" , sizeof( oheaders ) ); 
    while(1)
    {
        char ch[1024]={0} ; 
         int ret = recv(fd,ch,sizeof(oheaders),0);
        if(ret == 0 )
        {
            printf("server has close this session\n" ) ; 
            return -1;
        }
        #ifdef WIN32 
        if(ret == SOCKET_ERROR)
        {
            return -1;
        }
        #else
        if(ret == EAGAIN)
        {
            return -1;
        }   
        #endif
        printf("recv size=%d\n" , ret) ; 
         memcpy(&oheaders,ch , sizeof(oheaders));
         printf("oheaders.type=%d,oheaders.head=%d,oheaders.length=%d\n",oheaders.type,oheaders.head,oheaders.length);
         if(oheaders.head==Protocol_Header)
         {
             break;
         }
         else
         {
             printf("receive error head\n") ; 
             return -1; 
         }
    }

    /***在这里根据type选择创建的类型 0Msg文言 1 文件输出***/
    handler = Factory::object(oheaders.type) ;
    if(!handler)
    {
        printf("tyep[%d] is error\n" , oheaders.type )  ;
        return -1; 
    }
    handler->config(strFileName.c_str());
    char buf[ReadIOCacheSize]={0};
    int bufreaded = 0 ; 
    /*查找匹配的正文.每次读取当前剩余的字节数与ReadIOCacheSize的最小值*/
    do
    {
        int sizeEach=(ReadIOCacheSize>( oheaders.length -bufreaded ) )?( ( oheaders.length -bufreaded ) ):(ReadIOCacheSize);
        memset(buf,0x00 ,sizeof(buf) ) ; 
        int ret = recv( fd , buf , sizeEach , 0   ) ; 
        #ifdef WIN32 
        if(ret == SOCKET_ERROR)
        {
            return -1;
        }
        #else
        if(ret == EAGAIN)
        {
            return -1;
        }   
        #endif
        bufreaded+=ret;

        handler->hander(buf ,ret ) ; 
        //printf("[%d receieved]%s\n",ret,buf) ; 
    }while(bufreaded < oheaders.length  ) ; 


    //检查包的结尾
    struct tail otail;
    memset( &otail , 0x00 , sizeof(otail) ) ;
    char tmp[1024] = {0} ; 
    recv(fd,tmp,sizeof(otail),0);
    memcpy(&otail , tmp , sizeof(otail)  ) ;
    printf("tail=%d\n" , otail.tail) ; 
    if( otail.tail != Protocol_Tail )
    {
        printf("receive error tail\n") ; 
        return -1;
    }
}

int main( int argc ,char ** argv)
{
    FileTransport*p = FileTransport::instance();
    p->setfile(argv[3]);
    p->Init(argv[1] ,atoi(argv[2]) ) ; 
    p->OpenCusor("1122222" ,"select * from aaaaaaa" ) ; 
    int i = p->Fetch3();
    return i ; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Modbus是一种通信协议,主要用于工业控制系统中进行设备之间的通信。Modbus TCP是基于TCP/IP网络的Modbus协议的一个变种。 Modbus TCP的通信架构是基于客户端-服务器模的,其中客户端是发送请求的一方,而服务器是响应请求的一方。通信的基本单元是“寄存器”,可用于存储和传输各种类的数据(如位、字节、整数、浮点数等)。 在Modbus TCP协议中,通信以数据帧的形式进行。数据帧由多个字段组成,包括事务标识符、协议标识符、长度字段、单元标识符、功能码以及数据等。其中,事务标识符用于识别不同的请求和响应,协议标识符用于标识Modbus TCP协议,长度字段表示数据帧的长度,单元标识符用于标识设备或网络节点的地址,功能码表示请求的类,数据字段存储请求或响应的具体数据。 Modbus TCP协议支持多种功能码,包括读写寄存器、读写线圈、读写输入寄存器等。通过这些功能码,客户端可以发送请求给服务器,服务器根据具体的功能码进行相应的操作并返回响应。例如,读取寄存器功能码用于从设备的寄存器中读取数据,客户端发送该请求给服务器,服务器根据请求读取寄存器中的数据后返回给客户端。 总的来说,Modbus TCP协议是一种通信协议,用于实现设备之间的通信。通过发送请求和接收响应,可以实现设备的数据读取和写入操作。这使得Modbus TCP成为工业控制系统中常用的通信协议之一。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值