0.网络基础知识
OSI参考模型和TCP/IP参考模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DrTRIttY-1611297556794)(C:\Users\123\Pictures\Markdown\clip_image001-1609747913085.png)]
TCP/IP协议栈: 传输层的协议有TCP 和 UDP,TCP 是面向连接的。 而 UDP 是面向无连接的。
面向连接: 面向连接分为三个阶段,建立连接,传输数据,释放连接。 TCP 建立连接时的 3 次握手 和 5 次挥手。
1.网络传输中要注意的问题?
字节序问题
在计算机中字节序分为大端存储和小端存储, 网络上传输的数据都是字节流,对于一个多字节数值,在进行网络传输的时候,先传递哪个字节?也就是说,当接收端收到第一个字节的时候,它将这个字节作为高位字节还是低位字节处理,是一个比较有意义的问题;
UDP/TCP/IP协议规定:把接收到的第一个字节当作高位字节看待,这就要求发送端发送的第一个字节是高位字节;而在发送端发送数据时,发送的第一个字节是该数值在内存中的起始地址处对应的那个字节,也就是说,该数值在内存中的起始地址处对应的那个字节就是要发送的第一个高位字节(即:高位字节存放在低地址处);由此可见,多字节数值在发送之前,在内存中因该是以大端法存放的;
所以说,网络字节序是大端字节序;
大端:低地址处放高字节
**小端:**低地址处放低字节
因此网络传输分为主机字节序和网络字节序
主机字节序:host 网络字节序: network 。因此存在字节序转化问题,相关函数如下
_to__: htons, htonl,ntohs,ntohl
s代表是16位,代表32位
对齐问题
计算机硬件为了更快的访问内存通常在计算机存储的时候进行对齐操作,
struct node1 {
int i;
char a;
int b;
};
struct node2 {
int i;
char a;
short c;
int b;
};
上面 2 个结构体在内存中都占据 12 个字节。他们在连续的内存中会产生空档。
内存对齐公式: 元素存放的首地址 % sizeof( 元素) = 0; 存放的首地址必须整除元素字节大小。
网络是字节流传输,因此在计算中要进行网络传输的数据不能进行字节对齐。
类型长度问题
C语言的类型定义在并没有一个具体的定义( 在32 64 位的机器上会不同)。C语言只是进行了一个大致的规定int 是一个字长,duoble 要大于 float 等。
因此在网络传输的数据要使用无关平台的定义: int32_t , uint32_t, int64_t , int8_t, uint8_t
3. Socket
Socket 接口是 TCP/IP 网络的API,Socket 的接口定义了许多函数或例程,程序员可以用他们来开发 TCP/IP 网络上的应用程序。
网络的 Socket 数据传输时一种特殊的 I/O , Socket 也是一种文件描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。常用的Socket类型有两种:流式Socket (SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。
Socket:
int socket(int domain, int type,int protocol);
此函数用于创建一个套接字。
domain是网络程序所在的主机采用的通讯协族(AF_UNIX和AF_INET等)。
AF_UNIX只能够用于单一的Unix 系统进程间通信,而AF_INET是针对Internet的,因而可以允许远程通信使用。type是网络程序所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM等)。
SOCK_STREAM表明用的是TCP 协议,这样会提供按顺序的,可靠,双工,面向连接的比特流。
SOCK_DGRAM 表明用的是UDP协议,这样只会提不可靠,无连接的通信。
protocol,由于指定了type,所以这个地方一般只要用0来代替就可以了。
此函数执行成功时返回文件描述符,失败时返回-1,看errno可知道出错的详细情况。
4.报式套接字 UDP
网络通信是端到端通信,换句话说是进程间通信(不局限与一台主机间的进程通信)。 数据传输的三要素是:源地址,目的地址,长度。 在网络通信中地址的表示为 IP+端口。 IP地址:表示的是电脑主机的哪一个网卡,端口号:表示的是哪一个进程。
报式套接字分为主动端和被动端, 被动端要接收数据肯定要先运行。被动端相当于灯塔,要表示自己的位置(IP + 端口号),自己是哪一个机器的哪一个线程。
被动端:(先运行)
-
取得socket
-
给socket取得地址 (地址包括IP和端口)
函数bind()用到的函数inet_pton(); 字符串形式的iP地址 转换成网络形式的IP地址
反函数有inet_ntop();
-
收/发消息
recv()
recvform() dgram 式的接收,
-
关闭socket
使用命令 netstat -anu
主动端:
1、取得socket
2、给socket取得地址 (可省略)
程序运行的时候会自动分配一个可以用的端口
3、发/收消息
sendto()
4、关闭socket
多点通信 :
stat -anu
主动端:
1、取得socket
2、给socket取得地址 (可省略)
程序运行的时候会自动分配一个可以用的端口
3、发/收消息
sendto()
4、关闭socket
多点通信 :