Linux5:Linux网络编程
1.网络基础
1.Internet -"冷战"的产物
2.TCP协议分成了两个不同的协议:
用来检测网络传输中差错的传输控制协议TCP
专门负责对不同网络进行互联的互联网协议IP
从此TCP/IP协议诞生
1983年ARPAnet上停止使用NCP,互联网上的主机全部使用TCP/IP协议,TCP/IP协议成为Internet中的“世界语”。
3.网络的体系结构
网络采用分而治之的方法设计,将网络的功能划分为不同的模块,以分层的形式有机组合在一起 每层实现不同的功能,其内部实现方法对外部其他层次来说是透明的。
每层向上层提供服务,同时使用下层提供的服务。
网络体系结构即指网络的层次结构和每层所使用的协议的集合。
两类非常重要的体系结构:OSI和 TCP/IP。
OSI模型相关的协议已经很少使用,但模型本身非常通用
OSI模型是一个理想化的模型,尚未有完整的实现
OSI模型共有七层
二层交换机,三层交换机
4.TCP/IP协议族体系
TCP/IP协议族体系是Internet事实上的工业标准。 一共有四层
应用层 | Relnet,FTP,HTTP,DNS,SMTP等 |
传输层 | TCP和UDP |
网络层 | IP,ICMP和IGMP,端到端传输 |
网络接口和物理层 | 以太网,令牌环网,FDDI,wifi,gps/2G/3G/4G,驱动(屏蔽硬件差异) |
5.网络各层的协议解释
1.网络接口和物理层
mac地址:48位全球唯一,网络设备的身份标识
ARP(Address Resolution Protocol):地址解析协议,IP地址找到mac地址
RARP(Reverse Address Resolution Protocol):mac地址--找到IP地址
PPP协议:拨号协议(GPRS/3G/4G)
2.网络层
IP地址
IP协议:Internet protocol(分为IPv4和IPv6)
ICMP(Internet Control Message Protocol):Internet控制管理协议,Ping 命令属于ICMP
IGMP(Internet Group Management Protocol):Internet分组管理协议,广播和组播
3.传输层
(1)TCP:(Transfer Control protocol,传输控制协议)提供面向连接的,一对一的可靠传输的协议
数据无误,数据不丢失,数据无失序
适用场景:
适合对传输质量要求较高,以及传输大量数据的通信
在需要可靠数据传输的场合,通常适用TCP协议
MSN/QQ等即时通讯软件的用户登录账号管理相关的功能通常采用TCP协议
(2)UDP:(User Datagram Protocol,用户数据报协议):提供不可靠,无连接的传输协议
适用场景:
发送小尺寸数据(如对DNS服务器进行IP地址查询时)
在接收数据,给出应答较困难的网络中适用UDP(如无线网络)
适合于广播/组播式通信中 MSN/QQ/Skype等即时通讯软件的点对点文本通讯以及音视频通常采用UDP协议
流媒体,VOD,VoIP,IPTV等网络多媒体服务中通常采用UDP方式进行实时数据传输
(3)SCTP:(Stream Control Transmission Protocol:流控制传输协议),TCP的增强版,他能实现多主机, 多链路的通信。
4.应用层
网页访问协议:HTTP/HTTPS
邮件发送接收协议:POP3(收)/SMTP(发),IMAP(可接受邮件的一部分)
FTP:文件传输协议
Telnet/ssh:远程登录
嵌入式相关
NTP:网络时钟协议
SNMP:简单网络管理协议(实现对网络涉及集中式管理)
RTP/RSTP:用于传输音视频的协议(安防监控)
6.网络的封包和拆包
TCP/IP协议下的数据包
7.网络预备知识
1.socket
是一个编程接口,是一个特殊的文件描述符(对他执行IO的操作函数,比如read,write,close等),并不仅限于TCP/IP协议,面向连接TCP,无连接UDP。 socket代表网络编程的一种资源
分类
1.流式套接字(SOCK_STREAM)。唯一对应TCP
提供了一个面向连接,可靠的数据传输服务,数据无差错,无重复的发送顺序接收。内射击流量控制,避免数据流淹没慢的接收方。数据被看作式字节流,无长度限制。
2.数据包套接字(SOCK_DGRAM)。唯一对应UDP
提供无连接服务器,数据包以独立数据包的形式被发送,不提供无差错保证,数据可能丢失或重复;顺序发送,可能乱序接收。
3.原始套接字(SOCK_RAW)。对应多个协议,发送穿透了传输层,可以对较低层次协议如IP,ICMP直接访问。
2.IP地址
IP地址是Internet中主机的标识,Internet中的主机要与别的机器通信必须具有一个IP地址,IP地址为32 位(Ipv4)或者128位(Ipv6),每个数据包都必须携带目的IP地址和源IP地址,路由器依靠此信息为数据包选择路由
表示的形式:常用点分形式,如202.38.64.10,最后都会转化成一个32位的无符号整数 mobileIPV6:local IP(本地注册的IP),roma IP(漫游IP)
特殊IP地址
局域网IP: 192.XXX.XXX.XXX 10.XXX.XXX.XXX
广播IP:xxx.xxx.xxx.255 255.255.255.255(全网广播) 网络风暴
组播IP:224.xxx.xxx.xxx ~239.xxx.xxx.xxx
3.端口号
16位数字,1-65535, 为了区分一台主机接收到的数据包应该转交给哪个任务进程处理,使用端口号来区别
预留端口,1-1023(FTP:24, SSH:22, HTTP: 80 ,HTTPS :469)
保留端口:1024-5000(不建议使用)
可以使用的端口: 5000~65535
TCP端口号与UDP端口号独立
网络里的通信是由 IP地址+端口号 来决定的
4.字节序
字节序是指不同的CPU访问内存中的多字节数据时候,存在大小端的问题
如果CPU访问的是字符串,则不存在大小端问题
一般来说X86/ARM : 小端模式
power/miop:arm作为路由时,大端模式
网络传输的时候采用大端模式
1.字节转换函数
把给定系统所采用的字节序称为主机字节序,为了避免不同类别主机之间在数据交换时由于对于字节序的不同而导致的差错,引入了网络字节序。
主机字节序到网络字节序
u_long htonl(u_long hostlong); //Host to Network Long
//htonl 把unsigned long int类型从主机序转换到网络序
u_short htons(u_short short);
网络字节序到主机字节序
u_long ntohl(u_long hostlong);
u_short ntohs(u_short short);
长整型函数通常用来转换 IP 地址,短整型函数用来转换端口号。当然函数的使用不限于此,任何格式化的数据通过网络传输时,都应该使用这些函数来转换字节序。
2.IP地址的转换
inet_aton() // Address To Network
将strptr所指的字符串转换成32位的网络字节序二进制值
(将一个字符串表示的点分十进制IP地址IP转换为网络字节序存储在addr中,并且返回该网络字节序表示的无符号整数)
inet_addr()
功能同上,返回转换后的地址
仅适用于IPV4,出错时返回-1。
局限性:不能用于255.255.255.255的转换
inet_ntoa()
将32位网络字节序二进制地址转换成点分十进制的字符串
inet_pton()
int inet_pton(int af, const char* src ,void* dst)
将IPV4/IPV6 的地址转换成binary格式
使用于IPV4/IPV6 能正确处理255.255.255.255的转换问题
参数:
1.地址协议族(AF_INET或AF_INET6)
2.src:是一个指针(填写分点形式的IP地址(主要指IPV4))
dst:转换的结果给到dst
inet_ntop(int af,const void *src,char *dst,socklen_t size) //network to presentation
把ipv4和ipv6的网络字节序变成本地的字符串形式的IP地址
参数
1.af:地址协议族(AF_INET或AF_INET6)
2.src:是一个指针(32)
3.dst:输出结果为32位点分形式的IP地址
4.size:长度
2.TCP编程
1.socket函数
int socket(int domain,int type,int protocol);
参数
domain
AF_INET
AF_INET6
AF_UNIX,AF_LOCAL
AF_NETLINK
AF_PACKET
type
SOCK_STREAM: 流式套接字,唯一对应于TCP
SOCK_DGRAM:数据报套接字,唯一对应着UDP
SOCK_RAW:原始套接字
protocol:返回值 一般填0,原始套接字编程时需填充
返回值:成功返回文件描述符,出错返回-1
如果是IPV6编程,要使用struct sockddr_in6结构体(man 7 IPV6),通常使用struct sockaddr_storage来编程
2.bind函数
int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen)
参数
sockfd:通过socket()函数拿到的fd
addr:采用struct sockaddr的结构体地址,通用结构体
struct sockaddr{
sa_family_t sa_family;
char sa_data[4]; }
struct sockaddr_in{ 基于Internel通信结构体
as_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
sin_zero; //填充字节,需清零 }
struct in_addr{ uint32_t s_addr; }
addrlen:地址长度