目录
一.预备知识
1.1IP与MAC
IP地址,用来标识主机
源IP地址:发送方主机的IP地址
目的IP地址:接受方主机的IP地址
MAC地址,用来标识网卡
源MAC地址:发送方主机的MAC
目的MAC地址:接收方主机的MAC
补充:数据基本都是跨局域网传送的,网络层封装的报头当中有IP与MAC,IP地址是不会改变的。
但数据跨网络到达另一个局域网时,其源MAC地址和目的MAC地址就会发生变化。
1.2端口号
作用:用来标识一台计算机中的一个进程。
介绍下socket通信:
通过IP与MAC可找到公网上的唯一主机,通过端口号可找到那台主机上的对应的进程
通过IP与MAC已经可以完成数据的传输了,但本质其实是两台计算机的进程在进行通信,是跨网络的,而端口号就是来标识计算机中的进程,也分为源端口号,目的端口号。
- 源端口号: 发送方主机的服务进程绑定的端口号,保证接收方能够找到对应的服务
- 目的端口号: 接收方主机的服务进程绑定的端口号,保证发送方能够找到对应的服务
补充内容:
1.端口号是传输层协议的内容。
2.进程间的通信有共享内存,消息队列等,以及套接字(跨网络)
3.一个端口号只能被一个进程占用。一个进程可以绑定多个端口号,但是一个端口号不能被多个进程同时绑定。
4.进程ID(PID)是用来标识系统内所有进程的唯一性的,它是属于系统级的概念;而端口号(port)是用来标识需要对外进行网络数据请求的进程的唯一性的,它是属于网络的概念。
底层可采用哈希的方式,建立了端口号和进程PID或PCB之间的映射关系
1.3TCP与UDP协议
TCP:要进行数据传输,二者要先进行连接
- 传输层协议
- 有连接的
- 可靠传输
- 面向字节流
UDP:进行数据传输时,不需要进行连接,发送数据即可,但无法确定数据的可靠性
- 传输层协议
- 无连接
- 不可靠传输
- 面向数据报
2.4网络字节序
大小端介绍
大端:高位存放在低地址,低位存放在高地址
小端:低位存放在低地址,高位存放在高地址
巧计:低低是小端
网络上的字节流内存一样,也有大小端之分。
TCP/IP协议规定,网络数据流采用大端字节序
,不管这台主机是大端机还是小端机, 都会按照这个TCP/IP规定的网络字节序来发送/接收数据。(发送数据时按内存地址从低到高的顺序发出,接受数据时是按内存地址从低到高的顺序保存)
使网络程序具有可移植性,调用以下库函数实现网络字节序和主机字节序之间的转换
#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,s代表的是16位的短整型,l代表的是32位长整形
- 如果主机是小端字节序,函数会对参数进行处理,进行大小端转换
- 如果主机是大端字节序,函数不会对这些参数处理,直接返回
二.socket编程接口
2.1socket常见API
创建套接字:(TCP/UDP,客户端+服务器)
int socket(int domain, int type, int protocol);
绑定端口号:(TCP/UDP,服务器)
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
监听套接字socket :(TCP,服务器)
int listen(int sockfd, int backlog);
接收请求:(TCP,服务器)
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
建立连接:(TCP,客户端)
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
2.2sockaddr结构
其中struct sockaddr_in是用于网络通信,struct sockaddr_un是用于本地通信。sockaddr_in结构体存储了协议家族,端口号,IP等信息,网络通信时可以通过这个结构体把自己的信息发送给对方,也可以通过这个结构体获取对端的这些信息。
为了能让套接字的网络通信和本地通信能够使用同一套函数接口,于是出现了sockeaddr
结构体。其中这三个结构体的头部前16位是一样的,这个字段叫做协议家族。所以在用这个函数时可以统一传入sockeadder结构体,在设置参数时就可以通过设置协议家族这个字段,来表明我们是要进行网络通信还是本地通信。
补充内容:
1.IPv4和IPv6的地址格式定义在netinet/in.h中,IPv4地址用sockaddr_in结构体表示,包括16位地址类型,16位端口号和32位IP地址。
2.IPv4、IPv6地址类型分别定义为常数AF_INET、AF_INET6。这样,只要取得某种sockaddr结构体的首地址,不需要知道具体是哪种类型的sockaddr结构体,就可以根据地址类型字段确定结构体中的内容。
3.socket API可以都用struct sockaddr* 类型表示,在使用的时候需要强制转化成sockaddr_in;这样的好处是程序的通用性,可以接收IPv4、IPv6,以及UNIX Domain Socket各种类型的sockaddr结构体指针做为参数。
3.UDP网络程序
介绍:制作一个server服务端,用来提供各种服务。制作一个client客户端,可向服务端发送请求,服务端接受数据并处理后,再将数据返回给客户端。都将二者进行封装为一个类。
3.1服务端
3.1.1服务端创建套接字
创建套接字函数:
int socket(int domain, int type, int protocol);
参数解释:
domain:创建套接字的域或者叫做协议家族,也就是创建套接字的类型。该参数就相当于struct sockaddr结构的前