Python socket编程在网络上的教程较少,菜鸟中也只是给出了一小段描述,在此我推荐白羽黑夜socket编程 | 白月黑羽 (byhy.net)其中的描写非常详细,本人也是在此学习的。
socket又被称作套接字,可以简单的看作是两个地址(ip,port地址)之间通过socket的函数来进行传递数据。
socket在客户端的定义:
# socket.socket([family[, type[, proto]]]) #family: 套接字家族可以使 AF_UNIX 或者 AF_INET。 #type: 套接字类型可以根据是面向连接的还是非连接分为 #SOCK_STREAM 或 SOCK_DGRAM。 #protocol: 一般不填默认为 0。 # 下面给出一段代码示例 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) address = ('127.0.0.1', 10086) #socket链接的地址需为元组的形式! s.connect(address)
socket在服务器端的定义,与服务器端类似:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) addr = ('127.0.0.1', 10086) s.bind(addr) # 绑定端口,参数为元组
很明显可以注意到,客户端与服务器端的地址是一致的(当然也可以不完全一样,在此不表)
一个简易的服务器端代码如下:
# 摘自白羽黑夜socket编程 | 白月黑羽 (byhy.net)
from socket import * # 主机地址为空字符串,表示绑定本机所有网络接口ip地址 # 等待客户端来连接 IP = '' # 端口号 PORT = 50000 # 定义一次从socket缓冲区最多读入512个字节数据 BUFLEN = 512 # 实例化一个socket对象 # 参数 AF_INET 表示该socket网络层使用IP协议 # 参数 SOCK_STREAM 表示该socket传输层使用TCP协议 s = socket(AF_INET, SOCK_STREAM) # socket绑定地址和端口 s.bind((IP, PORT)) # 使socket处于监听状态,等待客户端的连接请求 # 参数 8 表示 最多接受多少个等待连接的客户端 s.listen(8) print(f'服务端启动成功,在{PORT}端口等待客户端连接...') data, addr = s.accept() print('接受一个客户端连接:', addr) while True: # 尝试读取对方发送的消息 # BUFLEN 指定从接收缓冲里最多读取多少字节 recved = dataSocket.recv(BUFLEN) # 如果返回空bytes,表示对方关闭了连接 # 退出循环,结束消息收发 if not recved: break # 读取的字节数据是bytes类型,需要解码为字符串 info = recved.decode() print(f'收到对方信息: {info}') # 发送的数据类型必须是bytes,所以要编码 datat.send(f'服务端接收到了信息 {info}'.encode()) # 服务端也调用close()关闭socket datat.close() s.close()
客户端代码如下:
from socket import * IP = '127.0.0.1' SERVER_PORT = 50000 BUFLEN = 1024 # 实例化一个socket对象,指明协议 datat = socket(AF_INET, SOCK_STREAM) # 连接服务端socket data.connect((IP, SERVER_PORT)) while True: # 从终端读入用户输入的字符串 toSend = input('>>> ') if toSend =='exit': break # 发送消息,也要编码为 bytes data.send(toSend.encode()) # 等待接收服务端的消息 recved = data.recv(BUFLEN) # 如果返回空bytes,表示对方关闭了连接 if not recved: break # 打印读取的信息 print(recved.decode()) data.close()
socket通常通过send(data)/sendto(data,address)进行消息发送,区别是一个给所有链接发送数据一个给指定地址发送数据。(私聊和群发的区别)
socket中所发的所有数据都需要进行编码,例如
data = '这是一条字符串' #不能用来作为send/sendto的参数 data = data.encode('utf-8') #也可以是别的编码格式 #此时data才能作为send/sendto的参数
接收端同样不能直接对接收到的数据进行print
需要对接收的假定为data=data.decode()进行解码,转化为字符串的形式才能print。