认识IP地址
IP协议有两个版本,IPv4和IPv6。无特殊说明,默认都是IPv4
- IP地址是在IP协议中,用来标识网络中不同主机的地址
- 对于IPv4来说,IP地址是一个4字节,32位的整数。IPv6,16字节。
- 我们通常使用“点分十进制”的字符串表示IP地址,如192.168.1.1;用点分割的每一个数字表示一个字节,范围为0-255
源IP地址和目的IP地址
在IP数据包头部中,有两个IP地址,分别叫做源IP地址和目的IP地址。
端口号
端口号是传输层协议的内容
1. 端口号是一个2字节16位的整数
2. 端口号用来标识这台主机唯一网络服务的一个进程
3. IP地址(找主机)+端口号(找网络进程)=套接字 能够标识网络上的某一台主机的某一个进程
4. 一个端口号只能被一个进程占用
一个进程可以绑定多个端口号;但是一个端口号不能被多个进程绑定
源端口号和目的端口号
传输层协议(TCP和UDP)的数据端口中有两个端口号,分别叫源端口号和目的端口号。在描述“数据是谁发出的,要发给谁”
认识TCP协议
TCP(传输控制协议)
1. 传输层协议
2. 有连接
3. 可靠传输
4. 面向字节流
认识UDP协议
UDP(用户数据报协议)
- 传输层协议
- 无连接
- 不可靠传输
- 面向数据报
网络字节序
网路数据流同样有大小端之分:
- 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出
- 接收主机把从网络上接收的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存
- 网络数据流应该这样规定:先发出的数据是低地址,后发出的数据是高地址。
- TCP/IP协议规定:网络数据流应采用大端字节序,即低地址高字节。
- 不管这台主机是大端机还是小端机,都会按照规定的 网络字节序来发送、接收数据
- 如果当前发送主机是小端,就需要先将数据转化成大端;否则就忽略,直接发送即可。
将0X12345abcd 写入到以0X0000开始的内存中,结果为:
大端:低地址高字节
big-endian
0X12
0X23
0Xab
0Xcd
最下边为高地址;二进制数 右边为低字节。
调用一下库函数做网络字节序和主机字节序的转换。
#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(网络),l表示32位长整数,s表示16位短整数。
- 例如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。
- 如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回。
- 如果主机是大端字节序,这些函数不做转换,将参数原封不动的返回。
socket编程接口
socket 常见API
//创建socket 文件描述符(TCP/UDP,客户端+服务器)
int socket(int domain,int type,int protocol); domain域名
//绑定端口号(TCP/UDP,服务器)
int bind(int socket,const struct sockaddr *address,socklen_t addrss_len);
//开始监听socket(TCP,服务器)
int listen(int socket,int backlog);
//接收请求(TCP,服务器)
int accept(int socket,struct sockaddr *address,socklen_t addrss_len);
//建立连接(TCP,客户端)
int connect(int socket,const struct sockaddr *address,socklen_t addrss_len);
sockaddr结构
socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4,IPv6,以及后面要讲的UNIX Domain Socket。各种网络协议的地址格式不相同。
socket API可以都用struct sockaddr*类型表示,在使用时余姚强制转换成sockaddr_in;这样的好处是程序的通用性,可以接收各种类型的sockaddr结构体指针作为参数。
sockaddr_in结构:
虽然socket api的接口是sockaddr,但是我们真正在基于IPv4编程时,使用的数据结构是sockadddr_in;这个结构里主要有三部分信息(地址类型,端口号,IP地址)
in_addr结构:
in_addr用来表示一个IPv4的IP地址,其实就是一个32位的整数。