一、服务器(主)
1、导入socket
import socket
2、定义
info_IP: tuple[str, int] = ("127.0.0.1", 4001) #元组[IP地址, 端口号]
home = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #通常这样写,详细的可以问度娘
home.bind(info_IP) #在这个 IP:端口 上建设一个接口
3、监听
socket 套接字在服务端创建后,会等待一个客户端来连接,因此需要监听端口
hom.listen(50)
#开放端口,传入的数字代表开发多少个,一般一个客户端连接后,就使用一个端口,直到结束通信
connect, address = home.accept()
#客户端连接后有返回两个值:
#connect通常为socket类型,连接后用它来通信;
#address为一个元组,包含客户端的地址和专属端口。
客户端的连接不能让服务器专注于这一个客户端,要不然其他客户端就连不进来了,所以循环监听
home.listen(500)
while True:
connect, address = home.accept()
4、通信
连接之后,用一个线程来并行处理这个客户端,主线程则需要继续监听
(一)导入多线程
import threading
(二)定义通讯内容
def chat(connect: socket.socket, add: tuple[str, int]):
address = f"{add[0]}:{add[1]}" #转换成标准的 IP:端口 格式
connect.sendall(address.encode("utf-8")) #把他的地址发还给他
print(connect.recv(1024 * 1024 * 1024).decode("utf-8")) #等待他的回复
#这里是重点
#发送字符串时,需要转成bits类型发送
#接受时,返回的也是bits类型
#接受时,recv(int),int为接受多少bits,最好为1024*1024*1024(1GB)
connect.sendall("hello".encode()) #发一个hello
print(connect.recv(1024 * 1024 * 1024).decode("utf-8")) #再一次等待回复
connect.sendall(open(file="./part data/up/text.txt", mode="rb").read()) #发送一个文件
#以bits只读打开(只读是r,bits是b,所以打开模式为rb)
connect.close() #结束通信
(三)定义并挂起线程
while True:
connect, address = home.accept()
# 客户端连接后有返回两个值:
# connect通常为socket类型,连接后用它来通信;
# address为一个元组,包含客户端的地址和专属端口。
threading.Thread(name=f"{address[0]}:{address[1]}", target=chat, kwargs={"connect": connect, "add": address}).start()
"""
name:线程名称
target:该线程要处理的代码(用函数封装)
kwargs:要传入的参数{"参数名":参数值,...}
"""
# start()表示挂起
服务端全代码
import socket
import threading
def chat(connect: socket.socket, add: tuple[str, int]):
address = f"{add[0]}:{add[1]}" #转换成标准的 IP:端口 格式
connect.sendall(address.encode("utf-8")) #把他的地址发还给他
print(connect.recv(1024 * 1024 * 1024).decode("utf-8")) #等待他的回复
#这里是重点
#发送字符串时,需要转成bits类型发送
#接受时,返回的也是bits类型
#接受时,recv(int),int为接受多少bits,最好为1024*1024*1024(1GB)
connect.sendall("hello".encode()) #发一个hello
print(connect.recv(1024 * 1024 * 1024).decode("utf-8")) #再一次等待回复
connect.sendall(open(file="./part data/up/text.txt", mode="rb").read()) #发送一个文件,以bits只读打开(只读是r,bits是b,所以打开模式为rb)
connect.close() #结束通信
info_IP: tuple[str, int] = ("127.0.0.1", 4001) #元组[IP地址, 端口号]
home = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #通常这样写,详细的可以问度娘
home.bind(info_IP) #在这个 IP:端口 上建设一个接口
home.listen(500)
while True:
connect, address = home.accept()
# 客户端连接后有返回两个值:
# connect通常为socket类型,连接后用它来通信;
# address为一个元组,包含客户端的地址和专属端口。
threading.Thread(name=f"{address[0]}:{address[1]}", target=chat, kwargs={"connect": connect, "add": address}).start()
"""
name:线程名称
target:该线程要处理的代码(用函数封装)
kwargs:要传入的参数{"参数名":参数值,...}
"""
# start()表示挂起
二、客户端(从)
1、定义并连接
过程稍稍不一样
info_IP: tuple[str, int] = ("127.0.0.1", 4001) #元组[服务端IP地址, 服务端口号]
connect = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #通常这样写,详细的可以问度娘
connect.connect(info_IP) #连接服务端IP上一个服务端口
2、通信
服务端通常只连接一个服务器,因此不需要多线程
#接下来每一步都要对上服务器
print(connect.recv(1024*1024*1024).decode()) #先接受发送的标准IP格式
connect.sendall("hello".encode()) #发送hello
print(connect.recv(1024*1024*124)) #接受hell0
connect.sendall("file".encode()) #发送file
open("./part data/down/text.txt",mode="wb").write(connect.recv(1024*1024*1024)) #接受发送的文件
"""
w:重写模式
b:bits
所以模式为wb
"""
connect.close() # 结束通信
服务端全代码
import socket
info_IP: tuple[str, int] = ("127.0.0.1", 4001) #元组[服务端IP地址, 服务端口号]
connect = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #通常这样写,详细的可以问度娘
connect.connect(info_IP) #连接服务端IP上一个服务端口
#接下来每一步都要对上服务器
print(connect.recv(1024 * 1024 * 1024).decode()) #先接受发送的标准IP格式
connect.sendall("hello".encode()) #发送hello
print(connect.recv(1024 * 1024 * 124)) #接受hell0
connect.sendall("file".encode()) #发送file
open("./part data/down/text.txt", mode="wb").write(connect.recv(1024 * 1024 * 1024)) #接受发送的文件
"""
w:重写模式
b:bits
所以模式为wb
"""
connect.close() # 结束通信