5.26日学习总结之网络编程socket

发布时间 2023-06-10 14:12:55作者: cassebl

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。