前言

说明:

  • 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. mysql 的基础操作

    1.建表 create table  表名( 字段一 数据类型 [列属性] , 字段二 数据类型 [列属性], ......... )[表类型][表字符集][注释]; 注意:MySQL命令终止符为分号 ...

  2. [小技巧] google map使用

    在网页中打开 google map 中,可以使用 shift + - 来缩小地图,shift + + 来放大地图.

  3. cke编辑器插入&ZeroWidthSpace占位字符的问题记录

    背景 本博文主要记录在使用cke编辑器时,遇到的一系列的问题 问题1:在执行某些业务操作后,编辑器会偶现在页面头部或者尾部插入&ZeroWidthSpace占位符(编辑器好像就爱干这事~) 解 ...

  4. Java8实战——自己的总结

    java8 介绍   java8是2014年3月份,由Oracle发布的一个版本,又称之为jdk1.8,是现再我们在学习和工作中用的最多的一个版本.   在jdk1.8中,java8以添加非常多的新特 ...

  5. mongodb oplog详解和格式分析

    1. 基本概念 oplog使用固定大小集合记录了数据库中所有修改操作的操作日志(新增.修改和删除,无查询),mongodb收到修改请求后,先在主节点(Primary)执行请求,再把操作日志保存到opl ...

  6. ArcnLinux安装基础配置(二)

    本文为对此ArchLinux安装使用教程网站中部分内容的总结和扩展补充,想看更详细的内容可以去此网站. 添加一个用户 useradd -m -G wheel -s /bin/bash cirry 设置 ...

  7. [刘阳Java]_大型电商网站架构技术演化历程

    今年的双十一已经过去一段,作为技术小咖啡,我们先说一下大型电商网站的特点:高并发,大流量,高可用,海量数据.下面就说说大型网站的架构演化过程,它的技术架构是如何一步步的演化的 1. 早期的网站架构 初 ...

  8. 替代Infinity绝佳的自主开发chrome插件

    最近闲来无事在好朋(da)友(shen)的帮助下开发一个chrome插件,目的是为了替换infinity主页插件, 当然在此也推荐一波infinity确实不错,界面和易用性都是非常好用的水准了. 主页 ...

  9. Java 使用新方法打印Word文档

    前言 我曾写过一篇文章,它主要介绍了如何通过物理打印机和虚拟打印机来打印Word文档.今天这篇教程将介绍一种新的方法来实现对Word文档的打印. 此次使用到的类库仍然是Spire.Doc for Ja ...

  10. shell编程-ssh免交互批量分发公钥脚本

    脚本基本原理 1.控制端免交互创建秘钥和公钥: 1 ssh-keygen -t rsa -f /root/.ssh/id_rsa -N "" 2.免交互发送公钥 1 sshpass ...