IP地址是在IP协议中,用来标识网络中不同主机的地址。IP协议有两个版本,IPv与IPv6,在一般情况下默认的都是IPv4。对于IPv4来说,IP地址是一个无符号四字节32位的整数(uint32_t)。 IP地址是在传输层协议的报头信息里所包含的。
在传输层的协议报头中通常有两个IP地址,分别是源IP地址(sip)和目的IP地址(dip),在网络中传输时,两个主机之间要进行通信,数据通过dip到达目的主机,而目的主机通过sip回复源主机。
当数据到达目的主机后,数据就会从下自上依次交付,到最后的应用层应该交付给哪个应用呢?一个主机有很多网络进程,每个网络进程只能处理自己的网络数据。这时候就需要一个东西来标识目的主机的目的网络进程------>端口号。
1、概念:端口号是一个2字节的16位整数,它类似于进程中的进程ID。端口号包含在传输层协议的报头信息里,并且在传输层协议的报头信息里有两个端口号,一个是一个是源端口号(sport),一个是目的端口号(dport),目的是为了两主机之间更好的通信。
2、作用:端口号会在传输层协议向应用层交付的时候,告诉操作系统这个数据要交付给应用层的哪一个网络进程。
3、在一台主机上,一个端口号标记着唯一的一个网络进程,但一个进程不一定对应一个端口号。对于不同的主机相同的进程,它们的端口号不一定是相同的。
我们知道所有数据在存储的时候都有大端小端之分。而不同的机器其存储方式也是不同的。那么如果两个主机在进行网络通信的过程中,发送与接收数据,由于不清楚对方的主机是大端存储还是小端存储,那么发送的数据的含义可能会被误解。所以网络数据流有大端小端之分。
大端字节序:低地址存高位 0x01(高地址) 02 03 04(低地址)--->0x01(低位)020304(高位)
小端字节序:低地址存低位 0x01(高地址) 02 03 04(低地址)--->0x04(低位)030201(高位)
不同字节序的主机之间进行数据传输,将造成数据的逆序,所以为了让不同主机字节序的主机之间进行正常的网络通信,在网络间进行通信的时候必须使用大端字节序,也就意味着如果我们的主机是小端字节序,那么通信的时候就需要对数据进行逆序。(逆序 主要针对的是在内存中存储时,占据大于1个字节的数据)
主机字节序:当前主机的字节序,它的大小端取决于cpu架构。 ( x86---->小端)
在进行网络传输数据的时候,就需要将主机字节序与网络字节序进行转换。
#include
- uint32_t htonl(uint32_t hostalong);
- uint16_t htons(uint16_t hostalong);
- uint32_t ntohl(uint32_t hostalong);
- uint16_t ntohs(uint16_t hostalong);
h:主机 n:网络 hton:主机到网络 l:32位长整数 s:16位短整数
为了保证代码的可移植性,一般都需要调用这些函数去进行转换。如果主机是小端的,那么调用过后将参数转成相应的大小端返回。如果是大端,那么就不做任何事情。
我们知道:一个IP地址对应网络中唯一的一个主机,一个端口号对应着一个主机上唯一的一个网络进程。而IP地址加端口号就可以对应在网络中唯一的一个网络进程。此时我们就可以通过IP地址加端口号的形式来查找到网络当中唯一的一个网络进程,而IP地址加端口号的形式就叫做套接字。
socket是操作系统提供的一套接口,目的是供用户进行网络通信编程
网络编程分为客户端程序和服务端程序,而客户端是主动的一方,并且客户端必须知道服务端的地址信息(ip+port/地址+端口),服务端也必须在这个指定的地址上进行等待。
使用场景:主要是在传输层,因为传输层有两个典型协议:tcp/udp,具体选择协议时要在进行数据传输时分情况而定。
优点:可靠传输,数据传输灵活;
缺点:传输速度较低,易 数据粘包(数据堆积造成数据粘连)
适用场景:针对数据安全性要求高的场景(文件传输等),保证数据的可靠性。
优点:传输速度快,无数据粘包。
缺点:不可靠。
适用场景:针对数据安全性要求不是很高,但是实时性要求高的场景(视频传输等),保证传输的速度。
// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);
// 绑定端口号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address, socklen_t address_len);
// 开始监听socket (TCP, 服务器)
int listen(int socket, int backlog);
// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address, socklen_t* address_len);
// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4,IPv6。其中IPv4地址用sockaddr_in来表示,包括16为地址类型,16位端口号和32为IP地址。IPv4地址类型分别为常数AF_INET与AF_INET6。
socket API可以都用struct sockaddr*类型表示,在使用的时候需要强制转化成sockaddr_in。
我们平常所看到的IP地址都是以点分十进制所表示的,而操作系统中对IP地址的看待都是二进制序列。并且sockaddr_in里的IP地址也是二进制序列,所以我们在使用的时候就需要将点分十进制的与二进制序列进行转化。
//点分十进制转in_addr函数
#include
int inet_aton(const char* strptr, struct in_addr* addrptr);
in_addr_t inet_addr(const char* strptr);
int inet_pton(int family, const char* strptr, void* addrptr);
---------------------------------------------------------------------------------
//in_addr转字符串的函数
char* inet_ntoa(struct in_addr inaddr);
const char* inet_ntop(int family, const void* addrptr, char* strptr, size_t len);