带指针的通信结构体32位与64位兼容


最近做一个移植项目,将32位上的VPN移植到64位环境上。由于当初设计未考虑可移植性,导致移植时出现了很多的问题,其中最典型的一个问题就是通信结构带指针的问题。

场景分析:

如下的两个结构体,其中B在通信时做通信结构使用

  1. struct A 
  2. int count; //链表结点数  
  3. int *b;            //数据链表  
  4. void* setPoint(void *p)//设置指针,传入起始指针,返回结束指针  
  5. return (int*)p + count; 
  6. struct B 
  7. int count;              //链表结点数  
  8. A *y;      //A结构链表  
  9. void* setPoint(void *p)  //设置指针,传入起始指针,返回结束指针  
  10. return  (A*)p+count; 

乍一看是不是很乱呢,确实,之所以在通信时使用这样的结构,是为了传送链表数据用的,也就是不固定的数据单元。

这里就不深入讨论这个结构的内存布局了,简单说一下,内存布局分为头部和尾部,头部为结构体数据,尾部为结构体所包含的链表数据。

移植分析

主要讨论移植的问题,众所周知,指针在32位下的长度为32位,而在64 位下的长度为64位,那么我们问题出现了。

我们知道,通信协议一定需要保证通信双方的数据包一模一样的,现在上面的这种情况如果32位与64位机通过B结构通信时,必然导致协议不一致而解析错误的问题。原因很简单,就是指针长度变了。

那么怎么解决这个问题了,首先想的当然是在64位机上采用一套跟32位机一模一样的结构体。

方法一、

在64位机上,多定义一套结构体(32位兼容结构),用int代替指针,请注意,由于指针在传到对端时必然失效,所以,这里的指针在通信过程中已经没有作用了。

用int做占位,处理时采用 标准结构体处理,在发送的时候将其转换成32位兼容结构,再发送出去,这样,对方在收到时就会协议兼容。

但问题是,这样做就会多做一次结构体解码和编码,即对整个多维链表的赋值,这是一个工作量很大的过程,特别当这样的结构多次出现时。

方法二、

自己实现一个指针类,用来替代结构体中出现的指针,该类模拟指针,但长度只有32位。

问题立刻出现了,怎么才能够用32位的长度模拟64位的指针呢,答案是不可能。

正常情况下确实是不可能的,应为无论如何,32位都没办法表示64位的长度。

但在这种通信结构中却是有可能的,因为通信结构大小一定小于2^32。

而通信结构中的指针指向的是通信结构中的某一个区域。

于是,可以采用偏移的方式模拟64位指针。

这样就很顺其自然地解决了所有的问题,只需要简单地对指针进行替换,就可以实现32与64位通信兼容

下面给出64位下模拟32位指针的简单实现:

  1. class ptr 
  2. private
  3. int shift; 
  4. public
  5. char* oprator=(char* p){ shift=(char*)this-p;return p;}  //计算出p相对于this的偏移,保存下来,用作下次计算指针实际值用  
  6. char* getptr(){return (char*)this + shift;} 

相关内容

    暂无相关文章