IP
网络的概念:将具有独立开发功能的计算机通过网线,网络设备(交换机,路由器),按照网络的软件以及协议,实现数据的传输·资源的共享
IP用于标识在网络中唯一的一台设备
IP地址分类
IPV4
IPV6
查看IP地址
window:cmd 输入ipconfig
mac/linux 输入ifconfig
查看网络是否通畅:ping IP/网址
端口和端口号
端口
数据传输的通道
端口号
端口的一个编号
端口号有65536个 0-65535
知名端口号:0-1023
动态端口号:1024-65535
TCP
TCP传输控制协议
面向连接的
建立连接
发送数据
关闭连接
可靠的
基于字节流的传输层的通信协议
socket
负责网络中进程之间数据的传输,数据的搬运工
TCP服务器程序开发
开发一个应用的时候,有两种架构
cs架构
client 客户端
server 服务器端
bs架构
browser 浏览器
server 服务器
TCP服务器程序的开发流程
1.创建TCP服务器端的socket对象
参数1: ‘AF_INET’, 表示IPv4地址类型
参数2: ‘SOCK_STREAM’, 表示TCP传输协议类型
2.绑定端口号 bind()
bind()参数是元组,如:(ip地址,端口号)
3.设置监听 listen()
参数:最大等待建立连接的个数
4.等待客户端的连接 accept()
返回:新的socket对象,IP地址和端口
5.接收消息 recv()
接收到的数据是字节类型
字节类型和字符串类型互相转换
字节转字符串
字节.decode(’编码格式‘)
字符串转字节
字符串.encode('编码格式')
6.发送消息 send()
7.关闭套接字 close()
源码
import socket
# 1. 创建TCP服务器端的套接字对象 socket
"""
参数 socket.AF_INET: 表示我们使用的IP地址的类型为 IPV4类型
socket.SOCK_STREAM: 表示的是我们使用的协议为TCP协议
"""
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 绑定端口号
"""
bind() 方法 接收的参数的类型是一个元组,元组中有两个元素
第一个元素的类型是一个字符串: 表示的是服务器绑定的ip地址,一般写一个空的字符串,表示任意的ip地址都可以连接服务器
第二个元素的类型是一个数字: 表示的是服务器绑定的端口号, 1024-65535
"""
tcp_server_socket.bind(("", 8088))
# 3. 设置监听
"""
listen() 这个方法用于设置监听, 这个方法接收一个参数,int类型的参数,接收一个数字
表示的是,监听的最大个数,一次最多可以有多少个客户端去连接我的服务器
"""
tcp_server_socket.listen(128)
# 4. 等待客户端的连接请求
"""
如果没有客户端连接,那么程序会阻塞在这一行代码,
accept() 这个方法,有两个返回值,
第一个返回值是一个新的socket对象,这个套接字是专门用于服务客户端的,后续接收和发送消息都使用这个新的套接字对象
第二个返回值,返回的是一个 元组。这个元组中有两个元素,第一个元素是 客户端的IP地址,第二个元素是客户端程序的端口号
"""
while True:
client_socket, ip_port = tcp_server_socket.accept()
print(f'接收到客户端 {ip_port} 的连接请求......')
# 5. 接收数据
"""
使用第四步获取到的socket对象来接收客户端发送来的数据, 使用 recv(num) 这个num 表示一次接收的字节数。
recv() 函数有返回值, 返回值的类型是一个 bytes 字节类型。
数据是在网络中传输的,网络中的数据在传输的时候都是使用的 bytes字节进行传输, 二进制方式进行传输。
所以在 使用 recv 接收到的数据就是一个 字节类型。 b'\xc4\xe3\xba\xc3\xd1\xbd'
想办法 将 bytes类型的数据 转换为 字符串类型
bytes类型数据 转换为字符串类型
字符串类型数据 转换为 bytes类型数据
"""
client_data = client_socket.recv(1024)
print(f'接收到客户端的消息:{client_data.decode("gbk")}')
# 6. 发送数据
"""
发送消息使用 新的套接字.send(), 注意: 发送数据的时候,数据的类型应该是 bytes
"""
client_socket.send("你好呀".encode("gbk"))
# 7. 关闭套接字对象
client_socket.close()
# tcp_server_socket.close()
注意点
-
TCP 服务端程序必须绑定端口号,否则客户端找不到这个 TCP 服务端程序。
-
listen 后(调用完listen方法的套接字)的套接字是被动套接字,只负责接收新的客户端的连接请求,不能收发消息
-
当 TCP 客户端程序和 TCP 服务端程序连接成功后, TCP 服务器端程序会产生一个新的套接字,收发客户端消息使用该套接字
-
关闭 accept 返回的套接字意味着和这个客户端已经通信完毕
-
关闭 listen 后的套接字意味着服务端的套接字关闭了,会导致新的客户端不能连接服务端,但是之前已经接成功的客户端还能正常通信
-
当客户端的套接字调用 close 后,服务器端的 recv 会解阻塞,(客户端连接上服务器之后,没有发送消息,断开了和服务器的连接,那么这个时候服务器会接收到一个数据,这个数据就是一个空数据,数据长度为0)返回的数据长度为0,服务端可以通过返回数据的长度来判断客户端是否已经下线,反之服务端关闭套接字,客户端的 recv 也会解阻塞,返回的数据长度也为0
-
TCP客户端开发
开发流程
1.创建socket对象
2.连接服务器
3.发送消息
4.接收消息
5.关闭套接字
源码
import socket
# 1. 创建socket对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 连接服务器
client_socket.connect(('192.168.82.169', 8088))
# 3. 发送消息
client_socket.send("服务器,我是客户端".encode('gbk'))
# 4. 接收消息
data = client_socket.recv(1024)
print(f'服务器返回的数据是: {data.decode("gbk")}')
# 5. 关闭套接字
client_socket.close()