前言

说明:

  • demo 基于 Linux。

3. 地址族与数据序列

// 	调用 bind 函数分配IP地址和端口号。
// 成功时返回0,失败时返回-1
#include <sys/socket.h>
int bind(int sockfd, struct sockaddr *myaddr, socklen_t addrlen); /* 补充 client 部分 */
// 成功时返回0,失败时返回-1
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

3.1 分配给套接字的 IP 地址与端口号

参考: 李柱明博客园

3.2 参数 IP 地址

由于原生的参数 struct sockaddr 类型不够直观,所以采用类型转换的 struct sockaddr_in 只要保证其字节大小一样,然后把其当做一段微内存即可。

3.2.1 IPV4 地址的结构体

// 原生,不建议直接用
struct sockaddr {
sa_family_t sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
}; // 格式转换后,推荐使用
struct sockaddr_in
{
sa_family_t sin_family; //地址族(Address Family)
uint16_t sin_port; //16 位 TCP/UDP 端口号
struct in_addr sin_addr; //32位 IP 地址
char sin_zero[8]; //为了保证其大小一致,目前不使用
}; struct in_addr
{
in_addr_t s_addr; //32位IPV4地址
}

3.2.2 地址族(Address Family)

成员 sa_family_t sin_family;

具体地址族类型参考 地址族(附件)

地址族(Address Family) 含义
AF_INET IPV4用的地址族
AF_INET6 IPV6用的地址族
AF_LOCAL 本地通信中采用的 Unix 协议的地址族

3.2.3 端口号

成员 uint16_t sin_port;

16 byte。

以网络字节序保存。(CPU 分大小端,为了统一,网络协同使用一种字节序来保证数据正确,到对端后再按需转换即可)

小知识

  • 可以这样区分 IP 和 端口号:一个主机可以共用一个 IP,端口号 用来区分主机程序。
  • 知名端口是要把该端口分配给特定的应用程序,范围是 0~1023 ,HTTP 的端口号是 80 ,FTP 的端口号是20和21。

3.2.4 IP 地址

成员 struct in_addr sin_addr;

32 byte。

以网络字节序保存。

小知识

  • 127.0.0.1 表示本机 IP。协议规定的。

3.2.5

成员 char sin_zero[8];

为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节,目前没有其它用途。

3.3 实例参考

注意:客户端创建socket后使用的函数是connect()。

#define cHOST "192.168.112.128" // 服务器端IP
#define cPORT 8080 // 服务器进程端口号 // 客户端
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET; // IPV4
serv_addr.sin_addr.s_addr = inet_addr(cHOST); // 地址
serv_addr.sin_port = htons(cPORT); //端口
//调用 connect 函数向服务器发送连接请求
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
error_handling("connect() error!");

3.4 网络字节序

3.4.1 字节序

得先了解大小端的问题。

本人的快速记忆是 小高高,意思是 字节放在位。

因为CPU有大小端的差异,如果不统一网络字节序就会导致数据交互错乱,如图:

网络字节序统一使用大端。

所以在收发前,先对数据进行检查、转换,再进行网络传输。

3.4.2 字节序转换相关函数

前后缀:

  • h:表示 host ,主机字节。
  • n:表示 network,网络字节。
  • s:表示 short。
  • l:表示 long。
unsigned short htons(unsigned short);
unsigned short ntohs(unsigned short);
unsigned long htonl(unsigned long);
unsigned long ntohl(unsigned long);

3.5 字符串转为网络字节序的整数形

3.5.1 inet_addr()

函数 inet_addr()

inet_addr是一个计算机函数,功能是将一个点分十进制的IP转换成一个长整数型数(u_long类型)等同于inet_addr()。

注意:一字节的范围为 [0:255]

// 返回:若字符串有效则将字符串转换为32位二进制网络字节序的IPV4地址,否则为INADDR_NONE
#include <arpa/inet.h> // Linux
in_addr_t inet_addr(const char* strptr); // 例子:
unsigned long conv_addrA = inet_addr("1.2.3.4"); // conv_addrA 为 0x4030201 unsigned long conv_addrB = inet_addr("1.2.3.256"); // conv_addr ERR,因为范围为 [0:255]

3.5.2 inet_aton()

函数 inet_aton()

函数 inet_aton() 和 函数 inet_addr() 在功能上是一样的,也是将字符串形式的IP地址转换成整数型的IP地址。

不同的是该函数得到的结果保存到 in_addr 结构体参数里面了,这样就可以判断有没有转换成功。

/*
string: 含有需要转换的IP地址信息的字符串地址值
addr: 将保存转换结果的 in_addr 结构体变量的地址值
成功时返回 1 ,失败时返回 0
*/
#include <arpa/inet.h>
int inet_aton(const char *string, struct in_addr *addr);

3.5.3 inet_ntoa()

函数 inet_ntoa()

该函数更好和 inet_aton() 相反,n -> a。

把网络字节整数型序转换为地址点分字符串形式。

特别注意

  • 该函数特点:其返回值为指针,实际内存实在函数里面申请的,该函数的实现里,只申请一次,下次调用时使用同样的已申请了的内存,(而不是重新申请,返回新的指针),所以下次调用该函数时,会把上次数据覆盖。
  • 使用注意:获取到返回的指针后,在下次调用该函数前,必须使用完毕或者把数据拷贝到新的内存里慢慢享受。
#include <arpa/inet.h>
char *inet_ntoa(struct in_addr adr);

3.6 网络地址初始化参考

struct sockaddr_in addr;
char *serv_ip = "192.168,1.2"; //声明IP地址族
char *serv_port = "8080"; //声明端口号字符串
memset(&addr, 0, sizeof(addr)); //结构体变量 addr 的所有成员初始化为0
addr.sin_family = AF_INET; //制定地址族
addr.sin_addr.s_addr = inet_addr(serv_ip); //基于字符串的IP地址初始化
addr.sin_port = htons(atoi(serv_port)); //基于字符串的IP地址端口号初始化

地址族(附件)

/* Supported address families. */
#define AF_UNSPEC 0
#define AF_UNIX 1 /* Unix domain sockets */
#define AF_LOCAL 1 /* POSIX name for AF_UNIX */
#define AF_INET 2 /* Internet IP Protocol */
#define AF_AX25 3 /* Amateur Radio AX.25 */
#define AF_IPX 4 /* Novell IPX */
#define AF_APPLETALK 5 /* AppleTalk DDP */
#define AF_NETROM 6 /* Amateur Radio NET/ROM */
#define AF_BRIDGE 7 /* Multiprotocol bridge */
#define AF_ATMPVC 8 /* ATM PVCs */
#define AF_X25 9 /* Reserved for X.25 project */
#define AF_INET6 10 /* IP version 6 */
#define AF_ROSE 11 /* Amateur Radio X.25 PLP */
#define AF_DECnet 12 /* Reserved for DECnet project */
#define AF_NETBEUI 13 /* Reserved for 802.2LLC project*/
#define AF_SECURITY 14 /* Security callback pseudo AF */
#define AF_KEY 15 /* PF_KEY key management API */
#define AF_NETLINK 16
#define AF_ROUTE AF_NETLINK /* Alias to emulate 4.4BSD */
#define AF_PACKET 17 /* Packet family */
#define AF_ASH 18 /* Ash */
#define AF_ECONET 19 /* Acorn Econet */
#define AF_ATMSVC 20 /* ATM SVCs */
#define AF_RDS 21 /* RDS sockets */
#define AF_SNA 22 /* Linux SNA Project (nutters!) */
#define AF_IRDA 23 /* IRDA sockets */
#define AF_PPPOX 24 /* PPPoX sockets */
#define AF_WANPIPE 25 /* Wanpipe API Sockets */
#define AF_LLC 26 /* Linux LLC */
#define AF_IB 27 /* Native InfiniBand address */
#define AF_MPLS 28 /* MPLS */
#define AF_CAN 29 /* Controller Area Network */
#define AF_TIPC 30 /* TIPC sockets */
#define AF_BLUETOOTH 31 /* Bluetooth sockets */
#define AF_IUCV 32 /* IUCV sockets */
#define AF_RXRPC 33 /* RxRPC sockets */
#define AF_ISDN 34 /* mISDN sockets */
#define AF_PHONET 35 /* Phonet sockets */
#define AF_IEEE802154 36 /* IEEE802154 sockets */
#define AF_CAIF 37 /* CAIF sockets */
#define AF_ALG 38 /* Algorithm sockets */
#define AF_NFC 39 /* NFC sockets */
#define AF_VSOCK 40 /* vSockets */
#define AF_KCM 41 /* Kernel Connection Multiplexor*/
#define AF_QIPCRTR 42 /* Qualcomm IPC Router */
#define AF_SMC 43 /* smc sockets: reserve number for
* PF_SMC protocol family that
* reuses AF_INET address family
*/

参考:

【网络编程】TCPIP_3_地址族与数据序列的更多相关文章

  1. TCP/IP网络编程之地址族与数据序列

    分配IP地址和端口号 IP是Internet Protocol(网络协议)的简写,是为收发网络数据而分配给计算机的值.端口号并非赋予计算机的值,而是为区分程序中创建的套接字而分配给套接字的序号 网络地 ...

  2. C/C++网络编程3——地址族与数据序列

    C/C++网络编程2中介绍了套接字,这一节介绍给套接字分配ip和端口号.ip用于标识一台主机,端口号用于标识一个主机中的一个应用程序,端口号占16位,0到65535,其中0到1023是知名端口号. 表 ...

  3. 【TCP/IP网络编程】:03地址族与数据序列

    上一篇文章介绍了套接字的创建过程,这篇文章主要讨论分配给套接字的IP地址和端口号的相关知识. IP地址和端口号 IP(Internet Protocol,网络协议)地址是收发网络数据而分配给计算机的值 ...

  4. 网络编程 --- URLConnection --- 读取服务器的数据 --- java

    使用URLConnection类获取服务器的数据 抽象类URLConnection表示一个指向指定URL资源的活动连接,它是java协议处理器机制的一部分. URL对象的openConnection( ...

  5. Linux网络编程-----Socket地址API

    (1) 通用socket地址 socket网络编程接口中表示socket地址的是结构体sockaddr,其定义如下: #include<bits/socket.h> struct sock ...

  6. Java网络编程:IP地址和端口号

    1)IP地址 用来标志网络中的一个通信实体的地址.通信实体可以是计算机,路由器等. 2)IP地址分类 IPV4:32位地址,以点分十进制表示,如192.168.0.1 IPV6:128位(16个字节) ...

  7. 网络编程--使用UDP发送接收数据

    package com.zhangxueliang.udp; import java.io.IOException; import java.net.DatagramPacket; import ja ...

  8. java网络编程_IP地址

    InetAddress类,此类表示Internet协议(IP)地址.具体使用方法查看文档:https://docs.oracle.com/en/java/javase/11/docs/api/java ...

  9. 网络编程 - 端口 & 地址占用

    1.设置地址复用(还可以设置端口复用): int enable=1; if (setsockopt(socketfd,SOL_SOCKET,SO_REUSEADDR,&iEnable,size ...

随机推荐

  1. 12 shell case in语句

    Shell也支持两种分支结构(选择结构),分别是 if else 语句和 case in 语句.当分支较多,并且判断条件比较简单时,使用 case in 语句就比较方便了. if else 语句与ca ...

  2. MySql数据库缓存

    对MySql查询缓存及SQL Server过程缓存的理解及总结 一.MySql的Query Cache 1.Query Cache   MySQL Query Cache是用来缓存我们所执行的SELE ...

  3. chrome 屏蔽广告的利器

    Adblock Plus https://chrome.google.com/webstore/detail/adblock-plus/cfhdojbkjhnklbpkdaibdccddilifddb ...

  4. linux驱动之获取设备树信息

    上一篇文章学习了字符设备的注册,操作过的小伙伴都知道上一篇文章中测试驱动时是通过手动创建设备节点的,现在开始学习怎么自动挂载设备节点和设备树信息的获取,这篇文章中的源码将会是我以后编写字符驱动的模板. ...

  5. OpenMVG 系列 (2):Image 和 Numeric

    OpenMVG 的功能模块由若干核心库组成,本文主要介绍 Image 和 Numeric 两个库 1  Image Image 库包含图像容器 Image<T>.图像IO读写函数 Read ...

  6. if函数+isna函数+vlookup函数实现不同列相同单元格内容排列在同一行

    1,首先学习的网址:https://jingyan.baidu.com/album/22a299b5dd0f959e19376a22.html?picindex=1 2,excel 这也许是史上最好最 ...

  7. MyEclipse无法打开jsp文件(打开是空白的),但是可以打开java文件

    转载: 解决MyEclipse使用时打开JSP发生"An error has occurred,See error log for more details"错误的解决方法这个问题 ...

  8. Java 比较两个Word文档差异

    本文介绍使用Spire.Doc for Java的比较功能来比较两个相似Word文档的差异.需要使用的版本为3.8.8或者后续发布的新版本.可下载jar包,解压将lib文件夹下的Spire.doc.j ...

  9. 利用docker-compose快速部署测试用数据库服务器

    起因 开发中经常需要快速部署一台随用随关的数据库服务器,如mysql,oracle,mongodb,elastic-search 尝试 一直觉得docker特别方便,加上docker-compose. ...

  10. Skywalking-02:如何写一个Skywalking trace插件

    如何写一个Skywalking trace插件 javaagent 原理 美团技术团队-Java 动态调试技术原理及实践 类图 实现 ConsumeMessageConcurrentlyInstrum ...