网络编程

typora-copy-images-to: 笔记

网络编程

1.引子

假如有两个脚本,foo.py,bar.py,分别运行,都可以正常运行。但是现在想从两个程序间传递一个数据。

  • 同一台电脑

    • 创建一个文件,将foo.py的数据读入文件中,bar.py从文件中读取数据。
  • 不同电脑间

    • 该怎么办?

软件的开发架构

C/S架构

C/S即Client和Server—>客户端和服务器端架构

B/S架构

B/S即Browser和Server —>浏览器端和服务器端架构

什么是网络

网络就是一种辅助双方或者多方能够连接在一起的工具。

伴随着网络发展,人们使用了很多通信方法,有些已不再使用,现在使用最广泛的是TCP/IP(Transmission Control Protocal/Internet Protocal)

TCPMP是标准协议,其可以使世界范围内的计算机通过Internet或本地网络通信。

TCP/IP事实上是一些协议(protocols)的合集。当前大多数使用中的通信都使用TCP协议。

Internet是在一些共享的线路上发送数据’的。例如:在您的计算机上也许同时运行着几个应用程序,如Web浏览器、通讯软件等程序,而您只须通过一条单一的线路来连接互联网。上面所有的程序都共享这个连接,简单地说,用户往往不会觉察到这个共享的发生。

目的

  • 使用网络把多方连接在一起,然后,进行数据传输。
  • 为了让不同电脑的软件可以互相传递数据,借助网络的功能。

网络编程的定义

让不同电脑中软件能够进行数据传递,即网络中不同主机进程间的通信。

地址

1. 生活中的地址与标识

不同的网络中,采用唯一的标识来区分不同的主体,比如车牌号、建筑物地址、电话号码、员工编号等等

一台电脑怎么找到很多电脑中的一台呢?

警察怎么找到嫌疑犯的?

2. ip地址的作用

ip地址:用来在网络中标记一台电脑,比如192.168.1.1;在同一网络中是唯一的。

同一网络:好比班级编号,球队编号。

同一网络:例如同一个局域网, 一个教室里。

3.IP地址分类

目前ip主要分为两种

  • ipv4,32位二进制构成。分成四段,每段范围0-255(2的八次方,四个字节)
  • ipv6,128位二进制构成。

每一个IP包含两部分:

  • 网络号
  • 主机号

类似电话号码由区号+电话主机号组成

C:\Users\ASUS>ipconfig

(1) IPv4可提供4,294,967,296个地址,IPv6将原来的32位地址空间增大到128位,数目是2的128次方。能够对地球上每平方米提供6×1023个网络地址,在可预见的将来是不会耗尽的。   
(2) IPv4 使用地址解析通讯协议 (ARP) ,IPv6使用用多点传播 Neighbor Solicitation 消息取代地址解析通讯协议 (ARP) 。   
(3) IPv4 中路由器不能识别用于服务质量的QoS 处理的 payload。IPv6中路由器使用 Flow Label 字段可以识别用于服务质量的 QoS 处理的 payload。      
(4) IPv4的回路地址为: 127.0.0.1,IPv6的回路地址为 : 000:0000:0000:0000:0000:0000:0000:0001 可以简写为 ::1。   
(5) 在IPv4中,动态主机配置协议( Dynamic Host ConfigurationProtocol,DHCP)实现了主机IP地址及其相关配置的自动设置。一个DHCP服务器拥有一个IP地址池,主机从DHCP服务器租借IP地址并获得有关的配置信息(如缺省网关、DNS服务器等),由此达到自动设置主机IP地址的目的。IP v6继承了IPv4的这种自动配置服务,并将其称为全状态自动配置(stateful autoconfiguration)。 m.pcwenku.com 供稿   
(6) IPv4使用 Internet 群组管理通讯协议 (IGMP) 管理本机子网络群组成员身份,IPv6使用 Multicast Listener Discovery (MLD) 消息取代 IGMP。   
(7) 内置的安全性。IPSec由IETF开发是确保秘密、完整、真实的信息穿越公共IP网的一种工业标准。IPsec不再是IP协议的补充部分,在IPv6中IPsec是IPv6自身所具有的功能。IPv4选择性支持IPSec,IPv6自动支持IPSec。   
(8) 更好的QoS支持。QoS是网络的一种安全机制,通常情况下不需要QoS,但是对关键应用和多媒体应用就十分必要。当网络过载或拥塞时,QoS 能确保重要业务量不受延迟或丢弃,同时保证网络的高效运行。在IPv6 的包头中定义了如何处理与识别传输, IPv6 包头中使用 Flow Label 来识别传输,可使路由器标识和特殊处理属于一个流量的封包。流量是指来源和目的之间的一系列封包,因为是在 IPv6 包头中识别传输,所以即使透过 IPSec 加密的封包 payload,仍可实现对 QoS 的支持。

二进制基数:0,1
八进制基数:0-7
十进制基数:0-9
十六进制基数:0-9,ABCDEF

二进制八进制十进制十六进制
0000 00010000 000110000 0001
0000 00100000 000220000 0002
0000 00110000 000330000 0003
0000 01000000 000440000 0004
0000 01010000 000550000 0005
0000 01100000 000660000 0006
0000 01110000 000770000 0007
0000 10000000 001080000 0008
0000 10010000 001190000 0009
0000 10100000 0012100000 000a
0000 10110000 0013110000 000b
0000 11000000 0014120000 000c
0000 11010000 0015130000 000d
0000 11100000 0016140000 000e
0000 11110000 0017150000 000f
0001 00000000 0020160000 0010
3.1 A类IP地址

一个A类IP地址由1字节的网络地址和3字节主机地址组成,网络地址的最高位必须是“0”,

地址范围1.0.0.1-126.255.255.254

二进制表示为:00000001 00000000 00000000 00000001 - 01111110 11111111 11111111 11111110

8位二进制全1就是255

可用的A类网络有126个,每个网络能容纳1677214个主机

3.2 B类IP地址

一个B类IP地址由2个字节的网络地址和2个字节的主机地址组成,网络地址的最高位必须是“10”,

地址范围128.1.0.1-191.255.255.254

二进制表示为:10000000 00000001 00000000 00000001 - 10111111 11111111 11111111 11111110

可用的B类网络有16384个,每个网络能容纳65534主机

3.3 C类IP地址

一个C类IP地址由3字节的网络地址和1字节的主机地址组成,网络地址的最高位必须是“110”

范围192.0.1.1-223.255.255.254

二进制表示为: 11000000 00000000 00000001 00000001 - 11011111 11111111 11111110 11111110

C类网络可达2097152个,每个网络能容纳254个主机

3.4 D类地址用于多点广播

D类IP地址第一个字节以“1110”开始,它是一个专门保留的地址。

它并不指向特定的网络,目前这一类地址被用在多点广播(Multicast)中

多点广播地址用来一次寻址一组计算机

地址范围224.0.0.1-239.255.255.254

网上视频会议、网上视频点播就是采用多点广播

广播地址 (Broadcast Address) 是专门用于同时向同一网络中所有主机发送数据的一个地址。在使用TCP/IP 协议的网络中, 主机标识段 HOST ID 为全1 的IP 地址为广播地址,广播分组传送给 HOST ID 段所涉及的所有计算机. 例如, 对于 192.168.50.26(255.255.255.0) 网段,其广播地址为192.168.50.255, 当发出一个目的地址为 192.168.50.255 的数据时, 它将被分发给该网段上的所有计算机. 飞秋,内网通就是通过广播地址来广播数据的

3.5 E类IP地址

以“1111”开始,为将来使用保留

E类地址保留,仅作实验和开发用

3.6 私有ip

在这么多网络IP中,国际规定有一部分IP地址是用于我们的局域网使用,也就

是属于私网IP,不在公网中使用的,它们的范围是:

10.0.0.0~10.255.255.255

172.16.0.0~172.31.255.255

192.168.0.0~192.168.255.255
3.7 回路地址

IP地址127.0.0.1~127.255.255.255用于回路测试,

如:127.0.0.1可以代表本机IP地址,用http://127.0.0.1就可以测试本机中配置的Web服务器。

网络通信过程

1. 两台电脑的网络

说明
  1. 如果两台电脑之间通过网线连接是可以直接通信的,但是需要提前设置好ip地址以及网络掩码
  2. 并且ip地址需要控制在同一网段内,例如 一台为192.168.1.1另一台为192.168.1.2则可以进行通信

2. 使用集线器组成一个网络

说明
  1. 当有多台电脑需要组成一个网时,那么可以通过集线器(Hub)将其链接在一起
  2. 一般情况下集线器的接口较少
  3. 集线器有个缺点,它以广播的方式进行发送任何数据,即如果集线器接收到来自A电脑的数据本来是想转发给B电脑,如果此时它还连接着另外两台电脑C、D,那么它会把这个数据给每个电脑都发送一份,因此会导致网络拥堵

3. 使用交换机组成一个网络

说明
  1. 克服了集线器以广播发送数据的缺点,当需要广播的时候发送广播,当需要单播的时候又能够以单播的方式进行发送
  2. 它已经替代了之前的集线器
  3. 企业中就是用交换机来完成多态电脑设备的链接成网络的

4. 使用路由器连接多个网络

5. 通信过程(复杂)

较为复杂的通信过程如:www.baidu.com

说明
  1. 在浏览器中输入一个网址时,需要将它先解析出ip地址来
  2. 当得到ip地址之后,浏览器以tcp的方式3次握手链接服务器
  3. 以tcp的方式发送http协议的请求数据 给 服务器
  4. 服务器tcp的方式回应http协议的应答数据 给浏览器

总结

  • MAC地址:在设备与设备之间数据通信时用来标记收发双方(网卡的序列号)
  • IP地址:在逻辑上标记一台电脑,用来指引数据包的收发方向(相当于电脑的序列号)
  • 网络掩码:用来区分ip地址的网络号和主机号
  • 默认网关:当需要发送的数据包的目的ip不在本网段内时,就会发送给默认的一台电脑,成为网关
  • 集线器:已过时,用来连接多态电脑,缺点:每次收发数据都进行广播,网络会变的拥堵
  • 交换机:集线器的升级版,有学习功能知道需要发送给哪台设备,根据需要进行单播、广播
  • 路由器:连接多个不同的网段,让他们之间可以进行收发数据,每次收到数据后,ip不变,但是MAC地址会变化
  • DNS:用来解析出IP(类似电话簿)
  • http服务器:提供浏览器能够访问到的数据

开放式系统互联参考模型(Open System Interconnection Reference Model)—>简称OSI

这个标准定义了网络的七层框架,试图使得计算机在整个世界范围内实现互联。
在OSI中,网络体系结构被分成下面的七层。

  • 物理层
    • 定义了通信设备的传输规范,规定了激活、维持和关闭通信节点之间的机械特性、电气特性和功能特性等。此层为上层协议提供了一个传输数据的物理媒介。
  • 数据链路层
    • 定义了数据封装以及传送的方式。这个层次的数据单位称为“帧”。数据链路层包括两个重要的子层:逻辑链路控制层(Logic Link Control,LLC)和介质访问控制层(Media Access Control,MAC)。LLC用来对节点间的通信链路进行初始化,并防止链路中断,确保系统的可靠通信。而MAC则用来检测包含在数据帧中的地址信息。这里的地址是链路地址或物理地址,是在设备制造的时候设置的。网络上的两种设备不能有相同的物理地址,否则会造成网络信息传送失败。
  • 网络层
    • 定义了数据的寻址和路由方式。这一层负责对子网间的数据选择路由,并实现网络互连等功能。
  • 传输层
    • 为数据提供端到端传输。这是比网络层更高的层次,是主机到主机的层次。传输层将对上层的数据进行分段并进行端到端传输。另外,还提供差错控制和流量控制机制。
  • 会话层
    • 用来为通信的双方制定通信方式,包括建立和拆除会话。另外,此层将会在数据中插入校验点来实现数据同步。
  • 表示层
    • 为不同的用户提供数据和信息的转换。同时还提供解压缩和加解密服务。这一层保证了两个主机的信息可以互相理解。
  • 应用层
    • 控制着用户绝大多数对于网络应用程序的访问,提供了访问网络服务的接口。

端口

整个网络通信通过IP地址+端口来标识不同的网络服务。

端口号是用来表示区别网络中不同的应用,操作系统会对端口进行编号,即端口号。

  • 端口号使用16位:也就是2个字节的数字来标识,范围0- 2 16 − 1 2^{16}-1 2161,0-65535

端口的分配是基于一定规则的,而不是随意分配的。

知名端口

80.分配给http服务
21,分配给FTP服务

动态端口(Dynamic Ports)

一般不固定分配某种服务,动态分配。范围:1024-65535

所谓的动态分配,是指一个程序需要网络通信时,它向主机申请一个端口,主机从可用的端口号中分配一个供其使用。关闭程序时,同时释放占用的端口。

端口查看:

netstat -ano

Socket简介

不同电脑上进程的标识与识别

用唯一标识来标记一个进程。

在电脑上,可以通过用进程号(PID)来唯一标识进程。但是在网络上,不可以。需要利用TCP/IP协议族来帮我们解决问题。

用IP可以唯一标识网络中的主机,协议+端口号唯一标识主机中的应用进程。

进程指的是,运行的程序以及运行程序时用到的资源的整体就称之为进程。

什么是Socket

socket(套接字)是进程间通信的一种方式。

与其他进程通信的一个主要不同是:

它能不同主机间的进程间的通信。

现行大多数服务器都是基于Socket来完成通信的。

比如:浏览网页,QQ聊天,收发Email。

创建一个socket

import socket
socket.socket(AddressFamily,Type)

参数说明:

  • AddressFamily
    • AF_INET Internet间进程间通信,实际工作最常用。
    • AF_UNIX,同一台机器进程间通信
  • Type套接字类型
    • SOCK_DGRAM,数据报套接字,主要用于UDP协议
    • SOCK_STREAM,流式套接字,主要用于TCP协议

server端

#server
import socket
#创建socket对象
serversocket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#主机名
host=socket.gethostname()
#端口号
port=9999
#绑定端口
serversocket.bind((host,port))
serversocket.listen(5)
while True:
    clientsocket,addr=serversocket.accept()
    print('链接地址:\t%s'%(str(addr)))
    msg='网络编程测试'+'\r\n'
    clientsocket.send(msg.encode('utf-8'))
    clientsocket.close()

client端

#cilent
import socket
#创建socket对象
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#获取本地主机名
host=socket.gethostname()
print(host)
#端口号
port=9999
#连接服务,指定主机和端口
s.connect((host,port))
#接收小于1024字节的数据
msg=s.recv(1024)
s.close()
print(msg.decode('utf-8'))

UDP网络程序

UDP—>User Data Protocol(用户数据报协议)是一个无连接的简单的面向数据报的运输层协议。

优缺点:

  • 优点:

    • 传输速度快(UDP在传输时无需在客户端和服务端之间建立连接,也无超时重新发送机制。
  • 缺点:

    • 不能保证可靠性(UDP是一种面向无连接的协议,每个数据都是一个独立的信息,包含完整的源地址或者目的地址,在网络上以任何可能的路径传往目的地。因此,能够到达目的地,以及到达目的地的时间和内容的正确性无法保证。)

特点:

UDP是面向无连接的通讯协议:

UDP包括目的端口号和源端口号信息,通讯不需要连接,能够实现广播发送。

UDP数据大小有限制,每个被传输的数据报必须限定在64K以内。

UDP是一个不可靠的协议,发送出去的数据报不一定以相同次序到达接收方。

UDP一般多用于多点通信和实时的数据业务。比如:

  • 视频
  • QQ
  • 语音广播等

发送数据

创建一个UDP客户端程序的流程:

1.创建一个客户端套接字

2.发送/接收数据

3.关闭套接字

socket和file的区别

  • file针对指定模块进行“打开”,“读写”,“关闭”
  • socket针对服务端和客户端socket进行“打开”,“读写”,“关闭”
import socket
udp_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
addr=("192.168.43.186",3456)
sendData=input("其请输入要发送的数据:")
udp_socket.sendto(sendData.encode("UTF-8"),addr)
udp_socket.close()

接收数据

import socket
udp_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
Addr=('192.168.43.186',3456)
sendData=input("请输入要发送的数据:")
udp_socket.sendto(sendData.encode("utf-8"),Addr)
recvData=udp_socket.recvfrom(1024)
print(recvData)
udp_socket.close()

用网络调试助手时,端口号会一直变动。

Socket 对象(内建)方法

函数描述
服务器端套接字
s.bind()绑定地址(host,port)到套接字, 在AF_INET下,以元组(host,port)的形式表示地址。
s.listen()开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。
s.accept()被动接受TCP客户端连接,(阻塞式)等待连接的到来
客户端套接字
s.connect()主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
s.connect_ex()connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
公共用途的套接字函数
s.recv()接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。
s.send()发送TCP数据,将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。
s.sendall()完整发送TCP数据,完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
s.recvform()接收UDP数据,与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。
s.sendto()发送UDP数据,将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。
s.close()关闭套接字
s.getpeername()返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。
s.getsockname()返回套接字自己的地址。通常是一个元组(ipaddr,port)
s.setsockopt(level,optname,value)设置给定套接字选项的值。
s.getsockopt(level,optname[.buflen])返回套接字选项的值。
s.settimeout(timeout)设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect())
s.gettimeout()返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None。
s.fileno()返回套接字的文件描述符。
s.setblocking(flag)如果flag为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常。
s.makefile()创建一个与该套接字相关连的文件

UDP端口号绑定

绑定端口

一般情况下,在一台电脑上运行的网络程序有很多,为了不与其他的网络程序占用同一个端口号,往往在编程中,udp的端口号一般不绑定。

但是如果需要做成一个服务器端的程序的话,是需要绑定的,想想看这又是为什么呢?

如果报警电话每天都在变,想必世界就会乱了,所以一般服务性的程序,往往需要一个固定的端口号,这就是所谓的端口绑定。

Demo:

import socket
udp_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
local_addr=("",3456)#IP地址和端口号,IP一般不用写,表示本地IP
udp_socket.bind(local_addr)

recv_data=udp_socket.recvfrom(1024)
print(recv_data[0].decode("gbk"))
udp_socket.close()

总结:

  • 一个udp网络程序可以不绑定端口,此时系统会自动分配一个端口,重新运行此程序,端口号可能会发生变化。
  • 一个udp网络程序可以绑定信息(IP,Ports)。如果绑定成功,那么操作系统用这个端口号来进行区别收到的网络数据是否是此进程的。

TCP简介

TCP协议,传输控制协议(Transmission Control Protocol),是一种面向连接的。可靠的、基于字节流的传输层通信协议。

TCP通信需要经过创建连接,传输数据,终止连接三个步骤。

TCP特点

面向连接

通信双方必须先建立连接才能进行数据的传输,双方都必须为该连接分配必要的系统内核资源,以管理连接的状态和连接上的传输。

双方间的数据传输都可以通过这个连接进行。

完成数据交换后,双方断开此连接,以释放系统资源。

这种连接是一对一的

因此TCP不适用于广播的应用程序,基于广播的应用程序请使用UDP协议

可靠传输

1)TCP采用发送应答机制

TCP发送的每个报文段都必须得到接收方的应答才认为这个TCP报文段传输成功

2)超时重传

发送端发出一个报文段之后就启动定时器,如果在定时时间内没有收到应答就重新发送这个报文段。

TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。

3)错误校验

TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。

  1. 流量控制和阻塞管理

流量控制用来避免主机发送得过快而使接收方来不及完全收下。

TCP和UDP的不同点
  • 面向连接
  • 有序的数据传输
  • 无差错的数据传输(重发丢失的数据包,舍弃重复的数据包)
  • 阻塞/流量控制
  • TCP通信模型,类似“打电话”,在通信开始前,一定要先建立相关连接,才能发送数据;而UDP通信模型,类似“写信”,不需要建立相关连接,只需要发送数据即可。

在python中,用TCP进行socket编程也比较简单,

  • 客户端
    • 要主动连接服务器的IP和指定端口
  • 服务器
    • 监听指定端口
    • 对于每一个新的连接,创建一个线程或者进程

通常,服务器程序可以无限运行下去。要注意的是,一个端口不能同时被两个socket绑定。

TCP服务端和客户端各自socket的创建和交互。

TCP服务器

在Python程序中,如果要完成一个TCP服务器的功能,需要的流程如下:

  • 1.socket创建一个套接字(买手机)

  • 2.bind()绑定IP和Port(插卡)

  • 3.listen()使用套接字由主动变为被动连接,即开始监听模式(设置一个响铃模式)

  • 4.accept()等待客户端的连接

  • 5.recv/send接受/发送数据

  • 6.关闭和客户端交互的套接字

  • 7.关闭监听套接字

服务端:

import socket

#创建套接字
tcp_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

#绑定本地信息
tcp_socket.bind(("",8080))#port num>1024的随意用,<1024的一般指定了用途

#设置监听
tcp_socket.listen(5)

#创建新的套接字
new_socket,addr=tcp_socket.accept()

#收/发数据
content=new_socket.recv(1024)
print("接收到的数据:",content.decode("utf-8"))

data=input("服务器发送的数据:")
new_socket.send(data.encode("utf-8"))

#关闭通信的socket
new_socket.close()

#关闭用于监听的套接字
tcp_socket.close()

设置监听的目的:

socket默认为主动模式,listen()能够将主动模式改为被动模式,被动了才能接收信息

listen(5),5是指可以同时接收到的客户端申请的最大数,超过则拒绝连接。

创建新套接字的原因:

服务器接收到请求后,将生成一个新的套接字,专门给新来的客户端提供一对一的服务,此时,服务器套接字接字的任务就是,等待新的客户端套接字连接它。

客户端:

import socket

#创建套接字
tcp_client_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

#目标服务器信息
server_ip=input("请输入服务器IP:")
server_port=int(input("请输入服务器port:"))

#连接服务器
tcp_client_socket.connect((server_ip,server_port))

#提示用户输入数据
send_data=input("请输入要发送的数据:")

tcp_client_socket.send(send_data.encode("utf-8"))

#接受服务器端发来的信息
recv_data=tcp_client_socket.recv(1024)
print("接收到的数据为:",recv_data.decode("utf-8"))

#关闭套接字
tcp_client_socket.close()

tcp注意点

  1. tcp服务端一般情况下都需要绑定,否则客户端找不到这个服务端
  2. tcp客户端一般不绑定,因为是主动连接服务端,所以只要确定好服务端的ip、port等信息就好,本地客户端可以随机
  3. tcp服务端中通过listen可以将socket创建出来的主动套接字变为被动的,这是做tcp服务端时必须要做的
  4. 当客户端需要连接服务端时,就需要使用connect进行连接,udp是不需要连接的而是直接发送,但是tcp必须先连接,只有连接成功才能通信
  5. 当一个tcp客户端连接服务端时,服务端会有1个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务
  6. listen后的套接字是被动套接字,用来接收新的客户端的连接请求的,而accept返回的新套接字是标记这个新客户端的
  7. 关闭listen后的套接字意味着被动套接字关闭了,会导致新的客户端不能够连接服务端,但是之前已经连接成功的客户端正常通信。
  8. 关闭accept返回的套接字意味着这个客户端已经服务完毕
  9. 当客户端的套接字调用close后,服务端会recv解堵塞,并且返回的长度为0,因此服务端可以通过返回数据的长度来区别客户端是否已经下线

TCP协议

当应用程序希望通过TCP与另一个应用程序通信时,他会发送一个通信请求。这个请求必须被送到一个确切的地址。在双方“握手”之后,TCP将在两个应用程序之间建立一个全双工(full-duplex)的通信。这个双工的通信将占用两个计算机之间的通信线路,直到他被一方或者双方关闭为止。

标志位,TCP的6个标志位

所谓标志位,一种二进制的指令

  • SYN:发起一个新连接
  • FIN:释放一个连接
  • ACK:确认

TCP三次握手

TCP是因特网的传输层协议,使用三次握手协议简历连接。当主动方发出SYN连接请求后,等待双方的回答SYN+ACK,并最终对对方的SYN执行ACK确认。这种建立连接的方法可以防止产生错误的连接。

TCP三次握手的过程

  • 客户端发送SYN(seq=x)报文交给服务器端,进入SYN_SEND状态;
  • 服务器端收到SYN报文,会因一个SYN(seq=y)+ACK(x+1)报文,进入SYN_RECV状态;
  • 客户端收到服务器端的SYN报文,回应一个ACK(y+1)报文,进入Established状态。

三次握手完成,TCP客户端和服务器端成功建立连接,可以开始传输数据。

TCP四次挥手

建立一个连接需要三次握手,而终止一个连接要经过四次挥手,这个是由TCP的半关闭(Half+close)造成的。

  • 1.某个应用进程首先调用close,称该端执行“主动关闭”(active close)。该端的TCP(tool center point)于是发送一个FIN字节,表示数据发送完毕

  • 2.接收到这个FIN的对端执行“被动关闭”(passive close),这个FIN由TCP确认。

注意:

FIN的接收也作为一个文件结束符(end-of-file)传递给接收端应用进程,放在已排队等候该应用进程接收的任何其他数据之后,因为FIN的接收意味着接收端应用进程在相关的连接上再无额外数据可接受。

  • 3.一段时间后,接收到这个文件结束符的应用进程将会调用close关闭它的套接字。这导致它的TCP也发送一个FIN。

  • 4.接收这个最终FIN的原发送端TCP(即执行主动关闭的那一端)确认这个FIN。(既然每段都需要一个FIN和一个ACK,因此,通常需要4个字节)

  • 广播

  • Mac地址

  • arp协议

  • 路由器

  • 局域网

  • 子网掩码

程**

  • 客户端发送SYN(seq=x)报文交给服务器端,进入SYN_SEND状态;
  • 服务器端收到SYN报文,会因一个SYN(seq=y)+ACK(x+1)报文,进入SYN_RECV状态;
  • 客户端收到服务器端的SYN报文,回应一个ACK(y+1)报文,进入Established状态。

三次握手完成,TCP客户端和服务器端成功建立连接,可以开始传输数据。

TCP四次挥手

建立一个连接需要三次握手,而终止一个连接要经过四次挥手,这个是由TCP的半关闭(Half+close)造成的。

  • 1.某个应用进程首先调用close,称该端执行“主动关闭”(active close)。该端的TCP(tool center point)于是发送一个FIN字节,表示数据发送完毕

  • 2.接收到这个FIN的对端执行“被动关闭”(passive close),这个FIN由TCP确认。

注意:

FIN的接收也作为一个文件结束符(end-of-file)传递给接收端应用进程,放在已排队等候该应用进程接收的任何其他数据之后,因为FIN的接收意味着接收端应用进程在相关的连接上再无额外数据可接受。

  • 3.一段时间后,接收到这个文件结束符的应用进程将会调用close关闭它的套接字。这导致它的TCP也发送一个FIN。

  • 4.接收这个最终FIN的原发送端TCP(即执行主动关闭的那一端)确认这个FIN。(既然每段都需要一个FIN和一个ACK,因此,通常需要4个字节)

  • 广播

  • Mac地址

  • arp协议

  • 路由器

  • 局域网

  • 子网掩码

img

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值