7-3python语法基础-网络编程-socket编程
socket
什么是socket?简述基于tcp协议的套接字通信流程。
socket就是套接字,
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,socket位于应用层和传输层之间,也就是说我们不直接和tcp协议和udp协议打交道,这些握手挥手都是socket承包了
socket是一组接口,这是一种门面模式,把复杂的tcp/ip协议隐藏到socket接口后面,
所以socket是接口,用于网络通信的,
Python Socket编程
使用python内置的socket库,目前socket编程,最多是通过tcp协议进行网络通讯的。
tcp进行通讯的程序双方,分为服务端和客户端。
tcp协议进行通讯的双方,是需要先建立一个虚拟连接的,然后双方程序员才能发送业务数据信息。
基于tcp的socket代码
服务端:
import socket
# 定义常量
IP = '127.0.0.1'
PORT = 8898
# 定义一次从socket缓冲区最多读入512个字节数据
BUF_SIZE = 512
# 第一步:创建socket对象
sk = socket.socket()
# 第二步:绑定ip和端口
sk.bind((IP, PORT)) # 注意这里参数是一个元组
# 第三步:监听端口
# 使socket处于监听状态,等待客户端的连接请求
# 调用了.listen,就把socket置于等待连接状态
# 参数5表示 最多接受多少个等待连接的客户端
sk.listen(5)
print(f'服务端启动成功,在{PORT}端口等待客户端连接...')
# 第四步:接收客户端连接,
# 无客户端连接时,就处于睡眠状态
conn, addr = sk.accept()
print('接受一个客户端连接:',addr)
# 第五步:接收客户端信息
while True:
# 尝试读取对方发送的消息
# BUF_SIZE 指定从接收缓冲里最多读取多少字节
ret = conn.recv(BUF_SIZE)
# 如果返回空bytes,表示对方关闭了连接
# 退出循环,结束消息收发
if not ret:
break
# 读取的学节数据是bytes类型,需要解码为字符串,上面接收到的都是字节,
info = ret.decode()
print(f'收到对方信息:{info}')
# 第六步:向客户端发送信息
# 发送的数据类型必须是bytes,所以要编码
conn.send(f'服务端接收到了信息{info}'.encode())
# 第七步:关闭客户端套接字,关闭服务器套接字(可选)
conn.close()
sk.close()
客户端:
import socket
# 定义常量
IP = '127.0.0.1'
PORT = 8898
# 定义一次从socket缓冲区最多读入512个字节数据
BUF_SIZE = 512
# 第一步:创建socket对象
sk = socket.socket()
# 第二步:连接服务器
sk.connect((IP, PORT))
while True:
# 从终端读入用户输入的字符串
toSend = input('>>>')
# 退出,跳出循环
if toSend == 'exit':
break
# 第三步:向服务器发送消息
# 也要编码为 bytes
sk.send(toSend.encode())
# 第四步:接收服务器返回
# 等待接收服务段的消息,如果没有消息就一直等待
recved = sk.recv(BUF_SIZE)
# 如果返回空bytes,表示对方关闭了连接
if not recved:
print("服务器关闭")
break
# 打印读取的信息
print(recved.decode())
# 第五步:关闭客户套接字
sk.close()
操作 | 服务端 | 客户端 | 备注 |
---|---|---|---|
socket.socket() | √ | √ | 两端都要先创建socket对象 |
bind() | √ | × | 服务端需要绑定ip和端口 |
listen() | √ | × | 服务端需要监听 |
connect() | × | √ | 客户端需要主动去连接 |
accept() | √ | × | 服务端需要被动接受连接 |
send() | √ | √ | 两端都可以发送信息 |
recv() | √ | × | 两端都可以接受信息 |
close() | √ | × | 两端都可以关闭连接 |
-
listen可以设置最大的连接数,因为服务器性能有限,所以需要可以设置最大连接数,
-
服务端的accept()与客户端的connect()创建双向管道, 这是建立通道的,
-
send(), recv(),是一对,可以收发信息
-
sk.sendall(string[,flag])
将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
内部通过递归调用send,将所有内容发送出去。 -
服务端一般都是需要一直开启的,所以需要一个死循环,
-
这个流程要记住,
基于udp的socket代码
服务端:
import socket
udp_sk = socket.socket(type=socket.SOCK_DGRAM) #创建一个服务器的套接字
udp_sk.bind(('127.0.0.1',9000)) #绑定服务器套接字
msg,addr = udp_sk.recvfrom(1024)
print(msg)
udp_sk.sendto(b'hi',addr) # 对话(接收与发送)
udp_sk.close() # 关闭服务器套接字
客户端:
import socket
ip_port=('127.0.0.1',9000)
udp_sk=socket.socket(type=socket.SOCK_DGRAM)
udp_sk.sendto(b'hello',ip_port)
back_msg,addr=udp_sk.recvfrom(1024)
print(back_msg.decode('utf-8'),addr)
技术改变命运