首页 > 代码库 > 从网络字节流中提出整数

从网络字节流中提出整数

最近在做一个项目,就是设计一套通信协议,利用nginx来实现解析。协议内容是包括整数和字符串,现在客户端收到服务器端发送的网络字节流时,需要从中提取出整数,再根据整数决定发送数据量的大小。如下所示:

p = u->buffer.pos;

num=*(int*)p

p指向接收到的网络字节流,用这么方式解析得到的整形num不是服务器端发送的数字,是一个很大的数。不对,于是换了种方式:

memcpy(num,p,sizeof(int));
printf("num is %d\n",*(int*)num);

结果还是一样。

但是输出字节流p,能看到后面的字符串是能得到的,但是前面的整数得不到

for(i=0;i<9;i++){
  printf("i :%c \n",p[i]);
}

于是改成以16进制形式输出,结果是可以查看到整数值:

pos last 0
pos last 0
pos last 0
pos last 5
pos last 77
pos last 67
pos last 70
pos last 31
pos last 66

即第4字节的那个5正式服务器端发送的数字,这说明网络字节流是对的。只是不能那样取出来。

这个时候就必须熟悉网络字节流的概念了,搜了下:

网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。
主机字节序就是我们平常说的大端和小端模式:不同的 CPU 有不同的字节序类型,这些字节序是指整数在内存中保存的顺序 这个叫做主机序。

就是网络字节流的序列和主机的序列可能不一样,所以需要一些函数进行转换,linux提供了四个函数:


为了进行转换 bsd socket提供了转换的函数 有下面四个
htons 把unsigned short类型从主机序转换到网络序
htonl 把unsigned long类型从主机序转换到网络序
ntohs 把unsigned short类型从网络序转换到主机序
ntohl 把unsigned long类型从网络序转换到主机序

 

把代码改成:

p=u->buffer.pos;
htnum=ntohl(*(int*)p);
printf("htmum=%d,%x\n",htnum,htnum);

搞定得到正确结果。

这说明进行网络编程时得注意网络字节流的序列,否则不能提取出对应的数据。