站长之家seo查找,肇庆市场核酸检测,上海一个人如何注册公司,数码公司网站建设的意义一、网络基础概念
1.1 网络
网络是由若干结点和连接这些结点的链路组成#xff0c;网络中的结点可以是计算机#xff0c;交换机、
路由器等设备。
1.2 互联网
把多个网络连接起来就构成了互联网。目前最大的互联网就是因特网。
网络设备有#xff1a;交换机、路由器、…一、网络基础概念
1.1 网络
网络是由若干结点和连接这些结点的链路组成网络中的结点可以是计算机交换机、
路由器等设备。
1.2 互联网
把多个网络连接起来就构成了互联网。目前最大的互联网就是因特网。
网络设备有交换机、路由器、集线器
传输介质有双绞线、同轴电缆、光纤无线 1.3 IP地址
IP 地址就是给因特网上的每一个主机或路由器的每一个接口分配的一个在全世界
范围内唯一的标识符。IP 地址因其特殊的结构使我们可以在因特网上很方便地进行寻址。
IP 地址有分 IPV4 和 IPV6 两种类别格式IPV4 是类似”A.B.C.D”的格式它是 32 位的用“.”分成四个段每个段是 8 个位值为 0-255用 10 进制表示。IPV6 地址是 128 位格式类似”XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX”用“:“分成 8 个段每个段 16 个位用 4 个 16 进制数表示。
接下来描述的 IP 地址默认都指的是 IPV4 的地址。为了便于寻址了解目标主机的位置每个 IP 地址由网络号和主机号两个部分构成。同一个物理网络上所有的主机都使用同 一个网络号只是主机号不同
1.4 inet_addr()
计算机使用的是无符号整型而用户熟悉的是点分十进制的字符串。
该函数可以将点分十进制字符串表示的ipv4地址转化为用网络字节序整数表示的ipv4.即无符号整型
1.5 查看ip地址方法
1、Windows
winr ---cmd--ipconfig 2、Linux
ifconfig
1.6 端口号
应用程序的代号进程号是会变的但是端口号不会变。所以我们使用端口号去唯一标识应用程序的。
1.7 127.0.0.1 127.0.0.1是回送地址指本地机一般用来测试使用。回送地址127.x.x.x是本机回送地址Loopback Address即主机IP堆栈内部的IP地址主要用于网络软件测试以及本地机进程间通信无论什么程序一旦使用回送地址发送数据协议软件立即返回不进行任何网络传输。 通信需要源ip端口 目的ip端口
1.8 协议
网络协议就是一组网络规则的集合是我们共同遵守的约定或标准。常见的协议 ◼ HTTP超文本传输协议 ◼ FTP: 文件传输协议 ◼ TELNET : 是 internet 远程登陆服务的标准协议。 ◼ TCP : 传输控制协议TCPTransmission Control Protocol是一种面向连接的、可 靠的、基于字节流的传输层通信协议 ◼ UDP 用户数据报协议 ◼ IP : Internet Protocol 简称 IP又译为网际协议或互联网协议 ◼ ICMP 因特网控制报文协议 ◼ ARP : 地址解析协议是根据 IP 地址获取 MAC 地址的协议 ◼ RARP : 逆地址解析协议 TCP报头 这里的ACKFIN,SYN后面介绍
1.9 服务器端编写
1.9.0 OSI 的 7 层模型与 tcp/ip 协议族体系 4 层结构**
1.9.0.1 OSI/ISO模型
应用层
表示层
会话层
传输层 加TCP/IP协议
网络层 加IP协议
数据链路层 加帧
物理层
1.9.0.2 TCP/IP模型
应用层
表示层
网络层
网际接口层数据链路层物理层
tcp的通信流程
1.9.1 创建套接字 int socket(int domain, int type, int protocol) 有了套接字就可以通过网络进行数据的收发
socket()创建套接字成功返回套接字的文件描述符失败返回-1
domain: 设置套接字的协议族 AF_INETIPv4和 AF_INET6(IPv6)
type: 设置套接字的服务类型 SOCK_STREAM(流服务,用于TCP协议)和SOCK_DGRAM(数据报用于UDP协议)
注意 PF开头的是协议族AF开头的是地址族在Windows上没有任何区别在Linux上差别不大 protocol: 一般设置为 0表示使用默认协议
1.9.2 命名socket int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 用来指定套接字使用的IP地址和端口。
bind()将 sockfd 与一个 socket 地址绑定成功返回 0失败返回-1
sockfd 是网络套接字描述符即socket()的返回值。
addr 是地址结构是一个结构体。
addrlen 是 socket 地址的长度。 专用 socket 地址结构
TCP/IP 协议族有 sockaddr_in 和 sockaddr_in6 两个专用 socket 地址结构体它们分
别用于 IPV4 和 IPV6
sin_family: 地址族 AF_INET
sin_port: 端口号需要用网络字节序表示在这里我们要注意大小端问题在不同的操作系统上大小端是不一样的为了方便我们的服务器端我们可以使用htons()函数将所有端口的字节序统一好。
sin_addr: IPV4 地址结构s_addr 以网络字节序表示 IPV4 地址 struct sockaddr_in { sa_family_t sin_family; u_int16_t sin_port; struct in_addr sin_addr; }; 1.9.3 监听socket
socket被命名后还不能马上接受客户连接我们需要使用如下系统调用创建一个监听队列以存放待处理的客户连接。 int listen(int sockfd, int backlog); listen()创建一个监听队列以存储待处理的客户连接成功返回 0失败返回-1
sockfd 是被监听的 socket 套接字
backlog 表示处于完全连接状态的 socket 的上限典型值为5
1.9.4 接受连接 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); accept()从 listen 监听队列中接收一个连接成功返回一个新的连接 socket
该 socket 唯一地标识了被接收的这个连接失败返回-1
sockfd 是执行过 listen 系统调用的监听 socket
addr 参数用来获取被接受连接的远端 socket 地址,一般是客户端
addrlen 指定该 socket 地址的长度
注意accept返回值为0表明我们的客户端结束标准输入这时我们接受到的值就为0.
1.9.5 TCP数据读写 ssize_t recv(int sockfd, void *buff, size_t len, int flags); ssize_t send(int sockfd, const void *buff, size_t len, int flags); recv()读取 sockfd 上的数据buff 和 len 参数分别指定读缓冲区的位置和大小
send()往 socket 上写入数据buff 和 len 参数分别指定写缓冲区的位置和数据长度
flags 参数为数据收发提供了额外的控制一般为0
1.9.6 关闭连接
关闭该连接对应的socket int close(int sockfd); close()关闭一个连接实际上就是关闭该连接对应的 socket
1.10 客户端编写
1.10.1 创建套接字 socket()
与服务器端一样
1.10.2 发起连接 int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); connect()客户端需要通过此系统调用来主动与服务器建立连接
成功返回 0失败返回-1
sockfd 参数是由 socket()返回的一个 socket。
serv_addr 是服务器监听的 socket 地址
addrlen 则指定这个地址的长度
1.10.3 发送数据 send()
与服务器端一样
1.10.4 接受数据 recv()
与服务器端一样
1.10.5 结束连接 close()
与服务器端一样
综上所述TCP协议的基本流程就是如下图所示 1.11 编写代码
1.0版本 只能进行一次通信
1.11.1 编写服务端(1.0)
#includestdio.h
#includestdlib.h
#includestring.h
#includeunistd.h
#includesys/socket.h
#includearpa/inet.h
#includenetinet/in.h
int main()
{int sockfdsocket(AF_INET,SOCK_STREAM,0);if(sockfd-1){exit(1);}struct sockaddr_in saddr,caddr;memset(saddr,0,sizeof(saddr));saddr.sin_familyAF_INET;saddr.sin_porthtons(6000);saddr.sin_addr.s_addrinet_addr(127.0.0.1);//当前主机的ip地址通过ifconfig获取int resbind(sockfd,(struct sockaddr*)saddr,sizeof(saddr));if(res-1){printf(bind err\n);exit(0);}reslisten(sockfd,5);if(res0){printf(listen err\n);exit(0);}while(1){int lensizeof(caddr);int caccept(sockfd,(struct sockaddr*)caddr,len);if(c0){continue;}printf(accept c%d\n,c);char buff[128]{0};int nrecv(c,buff,strlen(buff)-1,0);printf(n%d\n,n);printf(buff%s\n,buff);send(c,ok,2,0);close(c);}
} 1.11.2 编写客户端(1.0) #includestdio.h
#includestdlib.h
#includestring.h
#includeunistd.h
#includesys/socket.h
#includearpa/inet.h
#includenetinet/in.h
int main()
{int sockfdsocket(AF_INET,SOCK_STREAM,0);if(sockfd-1){printf(socket err\n);exit(1);}struct sockaddr_in saddr;memset(saddr,0,sizeof(saddr));saddr.sin_familyAF_INET;saddr.sin_porthtons(6000);saddr.sin_addr.s_addrinet_addr(127.0.0.1);//注意服务器和客户端必须要连接在同一个网络下int resconnect(sockfd,(struct sockaddr*)saddr,sizeof(saddr));if(res-1){printf(connect err\n);exit(0);} printf(input:\n);char buff[128]{0};fgets(buff,128,stdin);send(sockfd,buff,strlen(buff)-1,0);memset(buff,0,128);recv(sockfd,buff,127,0);printf(recv:%s\n,buff);close(sockfd);
}
结果 服务器端可以accept到客户端发送来的数据
客户端可以将服务器端接收到数据后返回的信息接受
二、 TCP 协议特点
2.1 连接的建立与断开
TCP 协议提供的是面向连接、可靠的、字节流服务。
使用 TCP 协议通信的双发必须先建立连接然后才能开始数据的读写。双方都必须为该连接分配必要的内核资源以管理连接的状态和连接上数据的传输。TCP 连接是全双工的双方的数据可以通过一个连接进行读写。完成数据交换之后通信双方都必须断开连接以释放系统资源。
TCP 的服务器端和客户端编程流程如下 socket()方法是用来创建一个套接字有了套接字就可以通过网络进行数据的收发。
bind()方法是用来指定套接字使用的 IP 地址和端口。
listen()方法是用来创建监听队列。监听队列有两种一个是存放未完成三次握手的连接一种是存放已完成三次握手的连接。listen()第二个参数就是指定已完成三次握手队列的长度。
accept()处理存放在 listen 创建的已完成三次握手的队列中的连接。每处理一个连接则accept()返回该连接对应的套接字描述符。如果该队列为空则 accept 阻塞。
connect()方法一般由客户端程序执行需要指定连接的服务器端的 IP 地址和端口。该方法执行后会进行三次握手 建立连接。
send()方法用来向 TCP 连接的对端发送数据。send()执行成功只能说明将数据成功写入到发送端的发送缓冲区中并不能说明数据已经发送到了对端。send()的返回值为实际写入到发送缓冲区中的数据长度。
recv()方法用来接收 TCP 连接的对端发送来的数据。recv()从本端的接收缓冲区中读取数据如果接收缓冲区中没有数据则 recv()方法会阻塞。返回值是实际读到的字节数如果recv()返回值为 0 说明对方已经关闭了 TCP 连接。
close()方法用来关闭 TCP 连接。此时会进行四次挥手
2.2 TCP 固定报头
TCP报头
ACK:表示确认号是否有效我们称携带ACK标志的TCP的报文段为确认报文段。
SYN:表示请求建立一个连接我们称携带SYN标志的TCP的报文段为同步报文段。
FIN表示通知对方本端要关闭连接了我们称携带FIN标志的TCP的报文段为结束报文段。
seqSequence Number表示这个tcp包的序列号。
2.3 三次握手
1第一次握手主机A向主机B发出请求数据包“我想给你发数据可以吗”这是第一次对话。
2第二次握手主机B向主机A发送同意连接并要求同步的数据包同步就是两台主机协调工作一台在发送一台在接收“可以你什么时候发”这是第二次对话。
3第三次握手主机A再发出一个数据包确认主机B的要求同步“我现在就发你接收吧”这是第三次对话。
握手发生在connet()的操作下。
主机A向主机B发送请求数据包这是第一次对话S表示SYN即请求建立一个连接
主机B向主机A 发送同意连接(回应 ACK,确认该序列号有效)并要求同步数据包SYN,所以有seq和ACK
主机A向主机B 发送一个数据包确认主机B的要求同步。ACK表示确认该序列号有效 2.4 中间传输信息
A主机给B主机发送了一个长度为3的字符串
B主机给A主机发送了一个长度为2的字符串,表明他收到该信息
A主机给B主机发送了确认收到的即ack 2.5 四次挥手
断开连接
四次挥手 三次挥手客户端和服务器端关闭相差不大这个时候就只有三次即中间的ACK和FIN合并在一起。
2.6 服务器端 (2.0)
服务器端和客户端可以进行多次交互直到客户端结束连接
#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h
#include sys/socket.h
#include arpa/inet.h
#include netinet/in.h
int main()
{int sockfd socket(AF_INET, SOCK_STREAM, 0);if (sockfd -1){exit(1);}struct sockaddr_in saddr, caddr;memset(saddr, 0, sizeof(saddr));saddr.sin_family AF_INET;saddr.sin_port htons(6000);saddr.sin_addr.s_addr inet_addr(127.0.0.1);int res bind(sockfd, (struct sockaddr *)saddr, sizeof(saddr));if (res -1){printf(bind err\n);exit(0);}res listen(sockfd, 5);if (res 0){printf(listen err\n);exit(0);}while (1){int len sizeof(caddr);int c accept(sockfd, (struct sockaddr *)caddr, len);if (c 0){continue;}while (1){printf(accept c%d\n, c);char buff[128] {0};int n recv(c, buff, 127, 0);if (n 0)//recv返回值n0表明客户端已经关闭连接了。{break;}printf(n%d\n, n);printf(buff%s\n, buff);send(c, ok, 2, 0);}sleep(2);close(c);}
}
如果将recv接受数据能力改成每次收取1个即int n recv(c, buff, 1, 0);
2.6.1 缓冲区 如果recv能力改成1那么每次只能从缓冲区中读取一个字符直到接收缓冲区中没有数据然后才会阻塞 2.6.2 查看缓冲区
netstat -natp
Recv-Q :接收缓冲区
Send-Q发送缓冲区
ESTABLLTSHED已完成三次握手 此时有2个ok在接收缓冲区在下一次输出
2.6.3 流失服务特点
不管中间如何分割但是最后从发送端到接收端得到的结果是一致的
可靠性
1应答确认超时重传机制
2去重报文有序号有相同序号会丢失重复的乱序重排报文有序号
2.6.4 粘包
粘包发生在发送或接收缓冲区中应用程序从缓冲区中取数据是整个缓冲区中有多少取多少那么就有可能第一个数据的尾部和第二个数据的头部同时存在缓冲区而TCP是流式的数据无边界这时发生粘包。 客户端发了三次数据服务器端一次接受完客户端在Recv()处等待服务器回应收到处于阻塞状态而服务器端处于第二次recv()所以阻塞这时这个粘包就会出现问题。解决方法就是在头部加上标识信息。
2.6.5 流量控制
TCP 协议是利用滑动窗口实现流量控制的。一般来说我们总是希望数据传输得更快一些不会一次只发一个字节。但是如果发送方把数据发得过快接受方就可能来不及接收这就会造成数据的丢失。所谓流量控制就是让发送方的发送速率不要太快要让接收方来的及接收。
在 TCP 的报头中有一个字段叫做接收通告窗口这个字段由接收端填充是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据而不会导致接收端处理不过来。所以发送端就会有一个发送窗口这个发送窗口的大小是由接收端填充的接收通告窗口的大小决定的并且窗口的位置会随着发送端数据的发送和接收到接收端对数据的确认而不断的向右滑动将之称为滑动窗口。发送方的滑动窗口示意图如下 2.7 客户端 (2.0)
#includestdio.h
#includestdlib.h
#includestring.h
#includeunistd.h
#includesys/socket.h
#includearpa/inet.h
#includenetinet/in.h
int main()
{int sockfdsocket(AF_INET,SOCK_STREAM,0);if(sockfd-1){printf(socket err\n);exit(1);}struct sockaddr_in saddr;memset(saddr,0,sizeof(saddr));saddr.sin_familyAF_INET;saddr.sin_porthtons(6000);saddr.sin_addr.s_addr inet_addr(127.0.0.1);int resconnect(sockfd,(struct sockaddr*)saddr,sizeof(saddr));if(res-1){printf(connect err\n);exit(0);} while(1){printf(input:\n);char buff[128]{0};fgets(buff,128,stdin);if(strncmp(buff,end,3)0){break;}send(sockfd,buff,strlen(buff)-1,0);memset(buff,0,128);recv(sockfd,buff,127,0);printf(recv:%s\n,buff);}close(sockfd);
} 2.8 多线程多进程并发
之前的代码存在一个问题当一个客户端与服务器建立连接以后服务器端 accept()返回进而准备循环接收客户端发过来的数据。如果客户端暂时没发数据服务端会在第 40 行的 recv()阻塞。此时其他客户端向服务器发起连接后由于服务器阻塞了无法执行 accept()接受连接也就是其他客户端发送的数据服务器无法读取。服务器也就无法并发同时处理多个客户端。
目的一个服务器能够同时收到多个客户端的数据
多线程
#include stdio.h
#include stdlib.h
#include unistd.h
#include string.h
#include sys/socket.h
#include arpa/inet.h
#include netinet/in.h
#include pthread.h
void * fun(void* arg)
{int *p (int*)arg;int c *p;free(p);while( 1 ){char buff[128] {0};int n recv(c,buff,1,0);if ( n 0)// recv返回值n 0 说明客户但关闭连接了{break;}
printf(recv%s\n,buff);send(c,ok,2,0);}
close(c);//关闭连接 挥手printf(client close\n);
}
int main()
{int sockfd socket(AF_INET,SOCK_STREAM,0);//套接字 文件描述符if ( sockfd -1 ){exit(1);}
struct sockaddr_in saddr,caddr;//套接字地址 ip port memset(saddr,0,sizeof(saddr));saddr.sin_family AF_INET;saddr.sin_port htons(6000);saddr.sin_addr.s_addr inet_addr(192.168.84.248);
int res bind(sockfd,(struct sockaddr*)saddr,sizeof(saddr));if ( res -1 ){printf(bind err\n);exit(1);}
res listen(sockfd,5);if ( res -1 ){exit(1);}
while( 1 ){int c accept(sockfd,NULL,NULL);if ( c 0 ){continue;}
printf(accept c%d\n,c);
pthread_t id;int * p (int*)malloc(sizeof(c));*p c;pthread_create(id,NULL,fun,(void*)p);}
}
多进程
使用fork()父子进程
#include stdio.h
#include stdlib.h
#include unistd.h
#include string.h
#include sys/socket.h
#include arpa/inet.h
#include netinet/in.h
void fun(int c)
{while( 1 ){char buff[128] {0};int n recv(c,buff,127,0);if ( n 0)// recv返回值n 0 说明客户但关闭连接了{break;}
printf(recv%s\n,buff);send(c,ok,2,0);}
close(c);//关闭连接 挥手printf(client close\n);
}
int main()
{int sockfd socket(AF_INET,SOCK_STREAM,0);//套接字 文件描述符if ( sockfd -1 ){exit(1);}
struct sockaddr_in saddr,caddr;//套接字地址 ip port memset(saddr,0,sizeof(saddr));saddr.sin_family AF_INET;saddr.sin_port htons(6000);saddr.sin_addr.s_addr inet_addr(192.168.84.248);
int res bind(sockfd,(struct sockaddr*)saddr,sizeof(saddr));if ( res -1 ){printf(bind err\n);exit(1);}
res listen(sockfd,5);if ( res -1 ){exit(1);}
while( 1 ){int c accept(sockfd,NULL,NULL);if ( c 0 ){continue;}
printf(accept c%d\n,c);
pid_t pidfork();if(pid0){printf(fork err\n);close(c);continue;}if(pid0){close(sockfd);fun(c);exit(0);}}
}
2.9 抓包
使用命令
netstat -natp
三次握手时 四次挥手时
因为时间原因没有截到 TIME_WAIT
三、 UDP 协议特点
UDP 数据报服务特点发送端应用程序每执行一次写操作UDP 模块就将其封装成一个 UDP 数据报发送。接收端必须及时针对每一个 UDP 数据报执行读操作否则就会丢包。并且如果用户没有指定足够的应用程序缓冲区来读取 UDP 数据则 UDP 数据将被截断。
与TCP不同的是UDP接收到的数据报会直接发给接收端不会存在缓存区。
1UDP是一个非连接的协议传输数据之前源端和终端不建立连接当它想传送时就简单地去抓取来自应用程序的数据并尽可能快地把它扔到网络上。
在发送端UDP传送数据的速度仅受应用程序生成数据的速度、计算机的能力和传输带宽的限制在接收端UDP把每个消息段放在队列中应用程序每次从队列中读一个消息段。
2由于传输数据不建立连接因此不需要维护连接状态包括收发状态等。一台服务机可同时向多个客户机传输相同的消息。
3UDP信息包的包头很短只有8字节相对于TCP的20字节包头信息UDP的包头开销很小。
4吞吐量不受拥挤控制算法的调节只受应用软件生成数据的速率、传输带宽、源端和终端主机性能的限制。
5UDP会尽最大努力去传输和接受数据且没有限制但并不保证可靠的数据交付主机也不需要维持复杂的链接状态表里面有许多参数。
6UDP是面向报文的。发送方的UDP对应用程序传过来的报文在添加包头后就向下交付给IP层。既不拆分也不合并而只是保留这些报文的边界因此应用程序需要自己限制合适的报文大小以免报文太大导致丢失率高。
3.1 API
UDP 数据读写
recvfrom()读取 sockfd 上的数据buff 和 len 参数分别指定读缓冲区的位置和大
小
src_addr 记录发送端的 socket 地址
addrlen 指定该地址的长度
sendto()往 socket 上写入数据buff 和 len 参数分别指定写缓冲区的位置和数据长
度
dest_addr 指定接收数据端的 socket 地址
addrlen 指定该地址的长度
ssize_t recvfrom(int sockfd, void buff, size_t len, int flags,struct sockaddr src_addr, socklen_t *addrlen);
ssize_t sendto(int sockfd, void buff, size_t len, int flags,struct sockaddr dest_addr, socklen_t addrlen);
3.2 服务器端
#include stdio.h
#include stdlib.h
#include unistd.h
#include string.h
#include sys/socket.h
#include arpa/inet.h
#include netinet/in.h
int main()
{int sockfdsocket(AF_INET,SOCK_DGRAM,0);if(sockfd-1){printf(socket err\n);exit(1);}struct sockaddr_in saddr,caddr;memset(saddr,0,sizeof(saddr));saddr.sin_familyAF_INET;saddr.sin_porthtons(6000);saddr.sin_addr.s_addrinet_addr(127.0.0.1);int resbind(sockfd,(struct sockaddr*)saddr,sizeof(saddr));if(res-1){printf(bind err\n);exit(0);}while(1){int lensizeof(caddr);char buff[128]{0};recvfrom(sockfd,buff,127,0,(struct sockaddr*)caddr,len);printf(buff%s\n,buff);sendto(sockfd,ok,2,0,(struct sockaddr*)caddr,sizeof(caddr));
}close(sockfd);exit(0);
}
3.3 客户端
#include stdio.h
#include stdlib.h
#include unistd.h
#include string.h
#include sys/socket.h
#include arpa/inet.h
#include netinet/in.h
int main()
{int sockfdsocket(AF_INET,SOCK_DGRAM,0);if(sockfd-1){printf(socket err\n);exit(1);}struct sockaddr_in saddr;memset(saddr,0,sizeof(saddr));saddr.sin_familyAF_INET;saddr.sin_porthtons(6000);saddr.sin_addr.s_addrinet_addr(127.0.0.1);while(1){print(input:\n);char buff[128]{0};fgets(buff,128,stdin);if(strncmp(buff,end,3)0){break;}sendto(sockfd,buff,strlen(buff)-1,0,(struct sockaddr*)saddr,sizeof(saddr));memset(buff,0,128);recvfrom(sockfd,buff,127,0,NULL,NULL);printf(buff%s\n,buff);
}close(sockfd);exit(0);
}
四、TCP和UDP区别
TCP安全、可靠、面向连接但是传输速度慢。UDP不安全、不可靠、面向非连接但是传输速度快。
TCP更适合与文件传输如果出现错误会重发。
UDP更适合于实时性如视频通话在网卡的情况下卡住网好后能够将实时的画面更新而不会把之前的再发一遍。