端口号(使用vi /etc/services 可以查看已经被占用的端口号)
为了区分一台主机接收到的数据包应该转交给哪个进程来进行处理,使用端口号来区别
TCP端口号与UDP端口号独立
端口号一般由IANA (Internet Assigned Numbers Authority) 管理
众所周知端口:1~1023(1~255之间为众所周知端口,256~1023端口通常由UNIX系统占用)
已登记端口:1024~49151
动态或私有端口:49152~65535
字节序
不同类型CPU的主机中,内存存储多字节整数序列有两种方法,称为主机字节序(HBO):
小端序(little-endian) - 低序字节存储在低地址
将低字节存储在起始地址,称为“Little-Endian”字节序,Intel、AMD等采用的是这种方式;
大端序(big-endian)- 高序字节存储在低地址
将高字节存储在起始地址,称为“Big-Endian”字节序,由ARM、Motorola等所采用
如何测试主机字节序:
方法1:使用指针
方法2:使用file命令,file a.out, 其中LSB的L代表小端存储
方法3:使用共用体
网络中传输的数据必须按网络字节序,即大端字节序
#include <arpa/inet.h>
将主机字节序转化为网络字节序
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
将网络字节序转化为主机字节序
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
1、使用共用体
#include <stdio.h>
//使用共用体测试主机字节序
union un{
int a;
char b;
};
int main(int argc, const char *argv[])
{
union un myun;
myun.a = 0x12345678;
printf("a = %#x\n", myun.a);
printf("b = %#x\n", myun.b);
if(myun.b == 0x78)
{
printf("小端存储\n");
}
else
{
printf("大端存储\n");
}
return 0;
}
2、使用short类型的指针判断
#include <stdio.h>
#include <arpa/inet.h>
int main(int argc, const char *argv[])
{
unsigned short endian = 0x1234;
// endian = htons(endian);
if(*(char *)&endian == 0x34)
{
printf("little endian!\n");
}
else
{
printf("big endian!\n");
}
return 0;
}
3、使用int类型的指针判断
本质上和使用short的方式是一样的。
#include <stdio.h>
//使用指针测试主机字节序
int main(int argc, const char *argv[])
{
int a = 0x12345678;
char *p;
p = (char *)&a;
printf("a = %#x\n", a);
printf("*p = %#x\n", *p);
if(*p == 0x78)
{
printf("little endian\n");
}
else
{
printf("big endian\n");
}
return 0;
}
测试结果
结论
主机为小端存储。一般除了网络为大端,其它的一般为小端。