tcpip基本数据结构讲解

传智扫地僧课程学习笔记。


IPv4套接口地址结构

 IPv4套接口地址结构通常也称为网际套接字地址结构,它以“sockaddr_in”命名,定义在头文件<netinet/in.h>

struct sockaddr_in {

uint8_t  sin_len; 4

sa_family_t  sin_family; 4

in_port_t sin_port; 2

struct in_addr sin_addr; 4

char sin_zero[8]; 8

};

  sin_len:整个sockaddr_in结构体的长度,在4.3BSD-Reno版本之前的第一个成员是sin_family.

  sin_family:指定该地址家族,在这里必须设为AF_INET

  sin_port:端口

  sin_addr:IPv4的地址;

  sin_zero:暂不使用,一般将其设置为0


通用地址结构

q  通用地址结构用来指定与套接字关联的地址。

struct sockaddr {

         uint8_t  sin_len;

         sa_family_t  sin_family;

         char sa_data[14]; //14

};

q  sin_len:整个sockaddr结构体的长度

q  sin_family:指定该地址家族

sa_data:由sin_family决定它的形式。


关于这两个结构,结论就是,你可以当它们两个一样,

比较关键的细节是,

第一个结构的前2个,与第二个结构的前两个,对应,

第一个结构的后3个,与第二个结构的最后一个对应,即3对1,

旁边标有大小,帮助你计算,

我还得再补一刀,现实中,第一种类型的可能有好几个,但是它们都向第二种通用的靠拢,

/*********************我是可爱的分割线*******************************/



字节序,

大小端的概念,我就不说了,每次都记不清,

主机字节序,也叫本地字节序,不同主机可能不同,

网络字节序,就是大端字节序,


就以这个例子,来记忆大小端,

0x 12  34  56  78 是我们要存储的数据,

----------------------------->>  这个是内存地址的增长方向,从0~XX

如果是12  34  56  78,就是大端字节序,

如果是78  56  34  12,就是大端字节序,

有时候文字理解,不是那么直观,

12345678就是大端字节序,顺~ 


下面就涉及到由于不同主机通过网络传输数据,引起的大小端转换,

来个题外话,XML就是一种处理的方式,

首先你就得判断,你自己的主机是大端还是小端,

int main()
{
	unsigned int data = 0x12345678;
	char *p = &data;
	printf("%x,%x,%x,%x\n", p[0], p[1], p[2], p[3] );
	
	if( p[0]==0x78)
	{
		printf("little model\n");  //我想写中文,小端的,可是尼玛我没安装中文,
	}
	else
	{
		printf("big model\n");
	}
	return 0;
}
我的电脑输出为 78,56,34,12

man 3 htonl,得到这些结果,

       #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);

h代表host;n代表network s代表short;l代表long,不过从后面uint32就可以大概看出来,

在上面代码的基础上,加上它,来使用系统提供的大小端转换函数,

	uint32_t mynetdata = htonl( data);
	p = &mynetdata;
	printf("%x,%x,%x,%x\n", p[0], p[1], p[2], p[3] );
转换为网络字节序,输出结果为 12,34, 56, 78



ip地址涉及到两种形式,

一种是我们平常常见的,即 192.168.0.1,另一种是计算机里面的32位bit的形式,

因此就涉及到两种形式的转换,

地址转换函数

 #include <netinet/in.h>

 #include <arpa/inet.h>

int inet_aton(const char *cp,struct in_addr *inp);

in_addr_t inet_addr(const char*cp);

char *inet_ntoa(struct in_addr in);

这几个函数,我是这样看的,

const代表输出参数,而struct _addr又是我们之前讲到过的ip地址结构体,

第一个函数的返回值,没有猜错的话,就是用来说明函数执行情况的,

char *类型,结合man文档,很容易想到是字符串类型的ip地址表示"192.168.0.1";


           struct sockaddr_in {
               sa_family_t    sin_family; /* address family: AF_INET */
               in_port_t      sin_port;   /* port in network byte order */
               struct in_addr sin_addr;   /* internet address */
           };


           /* Internet address. */
           struct in_addr {
               uint32_t       s_addr;     /* address in network byte order */
           };

第二个结构体定义的in_addr被用于第一个结构体中的元素,

int main()
{
	
	char *a = "192.168.6.222";
	in_addr_t myint = inet_addr( a);
	printf("%u\n", myint);
	
	struct in_addr inp;
	inet_aton( "192.168.6.222", &inp);
	printf("%u\n", inp.s_addr);
	
	a = inet_ntoa( inp);
	printf("%s\n", a);
	return 0;
}
输出结果为:

3724978368
3724978368
192.168.6.222,

老师说第三个函数,请深刻理解为什么不传入指针,而是元素,



/* 上面第二个示例代码,
究竟是定义指针,还是直接定义实体?
指针的话,你还得去分配内存,
实体的话,就相当于已经分配了内存,
但是地址得显示引用
*/








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值