1.Ip地址
-
ip地址介绍:
- ip地址就是 标识 网络中设备 的一个地址,好比 现实生活中 家庭地址
- ip 地址分为两类: IPv4 和 IPv6
- IPv4 是目前使用的ip地址
IPv6 是未来使用的ip地址 IPv4 是由点分十进制组成 IPv6 是由冒号十六进制组成 -
ip地址的作用:
- ip地址的作用是 标识网络中唯一的一台设备,也就是说通过 ip 地址能够找到网络中某台设备
-
查看ip地址
- Linux 和mac OS 使用ifconfig 这个命令
- windows 使用ipconfig 这个命令
- 一般情况下:
- 192.168.1.107 设备在网络中的ip地址
- 127.0.0.1表示本机地址
- 127.0.0.1 该地址对应的域名是localhost ,域名是ip地址别名,通过域名能解析出一个对应的ip地址
- 都是用来查看网卡信息的,其中包含地址
-
检查网络是否正常 使用ping命令
- piing www.baidu.com 检查是否能上公网
- ping 当前局域网的ip地址 检查是否在同一个局域网内
- ping 127.0.0.1 检查本地网卡是否正常
2.端口和端口号
不同电脑上的软件间进行数据通信,他是如何保证把数据传给相应软件而不是其他软件呢? 其实,每运行一个网络程序都会有一个端口,想要给对应的程序发送数据,找到对应的端口即可
-
端口是什么?
- 端口就是传输数据的通道,好比教室的门,是数据传输的必经之路
- 每一个端口都有一个端口号,就好比每间教室都有一个门牌号,想要找到端口通过端口号即可
-
什么是端口号?
- 操作系统为了统一管理,就对端口号进行了编号,这就是端口号,端口号其实就是一个数字,好比现实中的门牌号
- 端口号有65536个
- 数据通信–通过ip地址找到对应设备–通过端口号找到对应端口–通过端口将数据传输给应用程序
-
端口和端口号的关系: 端口号可以标识唯一的端口 -
端口号分类:
- 知名端口号
- 知名端口号是指众所周知的端口号,范围 0-1023
- 这些端口号一般是固定分配给一些数据,比如21端口分配给FTP(文件传输协议)服务器,25端口分配给SMTP(简单邮件传输协议) 服务,80端口分配给HTTP服务
- 动态端口号
- 一般指程序员没有设置端口号,操作系统会在动态端口号这个范围内随机生成一个给开发的应用程序使用
- 当运行一个程序默认会有一个端口号,当这个程序退出时,所占用的这个端口号就会被释放
-
端口的作用就是给运行的程序提供传输数据的通道 -
端口号作用是用来区分和管理不同端口的,通过端口号能找到唯一的一个端口 -
知名端口号范围: 0-1023 -
动态端口号范围: 1024-65536
3.TCP
简称: 传输控制协议 是一种面向连接的(发送前先建立连接,因此连接被关闭时则无法发送),可靠的,基于字节流(二进制数据)的传输层通信协议
- 网络应用程序之间的通信流程
- 通过ip找设备–通过端口号找端口-通过端口将数据传给应用程序
- 数据不能随便发送,在发送之前还需选择一个对应的传输协议,保证程序之间按照指定的传输规则进行数据的通信,这个传输协议就是TCP
- TCP 通信步骤
- 创建连接
- 传输连接
- 关闭连接
- TCP通信模型就相当于生活中的打电话,建立连接–发送数据(遵循TCP协议,socket完成进程间网络数据传输)–关闭
- TCP特点:
- 面向连接的 通信双方必须先建立连接-传输数据–关闭
- 可靠传输
- TCP采用发送应答机制
- 超时重传
- 错误检验(会自动调节数据包错误的顺序)
- 流量控制和阻塞管理(广播是UTP,没有控制)
- 流量控制:如果对方没有来得及接受,会将数据写在网卡的缓冲区里,网卡缓冲区是有上限的,等缓冲区的数据接受了在接着发送,好处是不会让对方的电脑卡死
- UTP是不可靠的传输协议,不论对方是否收到,只管发,最后会让对方电脑卡死
- 现在的共屏软件是UTP(使用UTP发送广播,TCP一般干不了)
- UTP不建立连接,不可靠,会出现丢包的情况,不太安全
4.socket
通信数据通过socket来完成
- socket 概念
- socket(简称 套接字)是进程之间通信的一个工具。好比现实生活中的 插座,所有的家用电器要想工作就要基于插座进行,进程间要进行网络通信需要基于这个socket
- 进程1 <—socket—>进程2
- socket作用:负责进程间的网络数据传输,好比 数据搬运工
- socket 应用场景:只要跟网络相关的应用程序或软件都 使用了 socket (浏览器 、qq)
5.TCP网络应用程序的开发流程
-
TCP 网络应用程序开发分为:
- TCP 客户端程序开发 运行在用户设备上的程序
- TCP 服务端程序开发 运行在服务器设备上的程序,专门给客户端提供数据服务
-
TCP 开发流程
-
客户端
- 创建客户端套接字对象
- 和服务端套接字建立连接
- 发送数据
- 接收数据
- 关闭客户端套接字
-
服务端
- 创建服务端套接字
- 绑定端口号
- 设置监听
- 等待接收客户端的连接请求
- 接收数据
- 发送数据
- 关闭套接字
-
主动发起建立连接请求的是客户端 -
等待接收连接请求的是服务端
6.开发TCP客户端
- 步骤:
- 创建客户端套接字对象
- 和服务器套接字建立连接
- 发送数据
- 接收数据
- 关闭客户端套接字
- socket 类
- 导入模块 import socket
- 创建客户端socket 对象 socket.socket(AddressFamily,Type) AddressFamily 表示IP地址类型,分为IPV4 和 IPv6 Type 表示传输协议类型
- 方法:
- connect(host,port) 表示和服务端套接字建立连接,host是服务器ip地址,port是应用程序端口号
- send(data) 表示发送数据,data是二进制数据
- recv(buffersize) 表示接受数据 ,buffersize是每次接受数据的长度
7.TCP服务端程序开发
- 步骤:
- 创建服务端套接字对象
- 绑定端口号
- 设置监听
- 等待接收客户端的连接请求
- 接收数据
- 发送数据
- 关闭套接字(可以不写)
- 方法:
- bind((host,port)) 表示绑定端口号,host 是ip地址,port是端口号 ip地址一般不指定,表示本机的任何一个ip地址
- listen(backlog) 表示设置监听,backlog 参数表示最大的等待连接的个数(最多128个)
- accept() 表示等待接收客户端的请求连接
- send(data) 表示发送数据,data是二进制数据
- recv(buffersize) 表示接收数据,buffersize是每次接收数据的长度
- 当客户端和服务端建立连接后,服务端程序退出后端口号不会立即释放,需要等待大概1~2分钟
- 解决办法:
- 更换服务端端口号
- 设置端口号复用(推荐使用),也就是让服务端程序退出后端口号立即释放
- 参数1 表示当前套接字
- 参数2 设置端口号复用选项
- 参数3 设置端口号复用选项对用的值
7.TCP网络应用程序的注意
- 当TCP客户端程序想要和TCP服务端程序进行通信的时候必须先建立连接
- TCP客户端程序一般不需要绑定端口号,因为客户端是主动发起建立连接的
- TCP服务端程序程序必须绑定端口号,否则客户端找不到这个TCP服务端程序
- listen后的套接字是被动套接字,只负责接收新的客户端连接请求,不能收发消息
- 当TCP客户端程序和TCP服务端程序建立连接成功后,TCP服务端程序会产生一个新的套接字,收发客户端消息使用该套接字
- 关闭accept返回的套接字意味着和这个客户端已经通信完毕
- 关闭listen 后的套接字意味着服务端的套接字已经关闭,会导致新的客户端不能连接到服务端,但之前已经连接成功的客户端还能正常通信
- 当客户端的套接字调用close 后,服务端的recv 会解阻塞,返回的数据长度为0 。服务端可以通过返回的数据长度来判断客户端是否已经下线,反之服务端关闭套接字,客户端的recv 也会解阻塞,返回的数据长度也为0。
8.多任务版TCP服务端程序开发
- 步骤:
- 编写一个TCP服务端程序,循环等待接收客户端的连接请求
- 当客户端和服务端建立连接成功,创建子线程,使子线程专门处理客户端请求,防止主线程阻塞
- 把创建的子线程设置为成为守护主线程,防止主线程无法退出
- 通过判断接受数据的长度来决定是否关闭此客户端的套接字
import socket
import threading
def handle_client_request(iport ,new_socket):
print('服务端接受的ip,端口号',iport)
new_socket.send('你好,这里是服务端'.encode('gbk'))
while True:
recv_data = new_socket.recv(1024)
if recv_data:
print(f'服务端就收端口号为{iport}的数据', recv_data.decode('gbk'))
else:
print(f'{iport}端口的客户端已下线')
new_socket.close()
break
if __name__ == '__main__':
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
tcp_server_socket.bind(('', 8888))
tcp_server_socket.listen(128)
while True:
new_socket,iport=tcp_server_socket.accept()
s1=threading.Thread(target=handle_client_request,args=(iport,new_socket),daemon=True)
s1.start()
9.socket之send与recv原理
- TCP soclet的发送和接收缓冲区
当创建一个TCP socket 对象的时候,会有一个发送缓冲区和接收缓冲区,这个发送和接收缓冲区指的就是内存中的一片空间 - send 的原理
send 是否直接把数据发给服务器了? 不是,要想发数据,必须通过网卡发送数据,应用程序是无法直接通过网卡发送数据的,它需要调用操作系统接口,也就是说,应用程序把发送的数据先写入到发送缓冲区(内存中的一个空间),在有操作系统控制网卡把数据缓冲区的数据发送给服务端网卡 - recv 原理
recv是否直接从客户端接收数据? 不是,应用软件是无法直接通过网卡接收数据的,它需要调用操作系统接口,由操作系统通过网卡接收数据,把接收的数据写入到接收缓冲区(内存中的一个空间),应用程序再从接收缓冲区获取客户端发送的数据
|