1.网络通信要素(IP+端口+传输协议)
2.Socket编程
2.1TCP、UDP协议了解
2.2 Socket流程
服务端有两个socket对象,客户端有一个
3.Socket实战
服务端代码:
import socket
#创建Socket对象
sk=socket.socket()
#绑定ip与端口号-使用元组传参
sk.bind(("127.0.0.1",13000))
#监听有没有请求过来
sk.listen()
print("服务端已经启动...")
#等待传入连接,在连接成功之前保持阻塞状态
#如果连接成功,会返回一个新的套接字和客户端ip与端口号
#新的套接字:conn-新的socket对象
conn,addr=sk.accept()
# print("客户端:",sk.accept())
print("客户端的ip地址是:",addr)
#接受客户端发生的数据-一次性接受多少字节.decode将bytes转为str
data=conn.recv(1024)
print("客户端发生的数据:",data.decode("utf-8"))
server_input=input("请输入>>>")
#发送数据encode(将str转为bytes)
conn.sendall(server_input.encode("utf-8"))
conn.close()
sk.close()
客户端代码
import socket
#创建socket对象
sk=socket.socket()
#发起连接
sk.connect(("127.0.0.1",13000))
#发送数据
client_input=input("请输入>>>")
sk.sendall(client_input.encode("utf-8"))
#接受数据-一次性接受多少字节
data=sk.recv(1024)
print("服务端响应数据:",data.decode("utf-8"))
sk.close()
sk.accept()
一旦有客户端发起连接,sk.accept() 方法会返回两个值:
一个是新的套接字对象 conn,用于与该客户端进行通信;
另一个是客户端的地址 address,表示客户端的网络位置。
上传和下载文件
客户端:
import socket,os
sk=socket.socket()
#发起连接
sk.connect(("127.0.0.1",13001))
def post_file(sk_obj,file_path):
"""
发送数据
:param sk_obj: 对象
:param file_path: 文件路径
:return:
"""
#发送文件大小os.stat可以得到文件所有信息
file_size=os.stat(file_path).st_size#获取文件大小
sk_obj.sendall(str(file_size).encode("utf-8"))
sk_obj.recv(1024)#避免粘包
#发送文件名字-分割文件路径
file_name=os.path.split(file_path)[1]
sk_obj.sendall(file_name.encode("utf-8"))
sk_obj.recv(1024) # 避免粘包
# 发送文件内容
with open(file_path, "rb") as f:
while file_size > 0:
sk_obj.sendall(f.read(1024))
file_size -= 1024
path="./1.jpg"
post_file(sk,path)
sk.close()
服务端:
import os,socket
#创建socket对象
sk=socket.socket()
#绑定ip和端口
sk.bind(("127.0.0.1",13001))
sk.listen()
def get_file(sk_obj):
"""
接受文件
:param sk_obj: socket对象
:return:
"""
#接受文件大小
file_size=(sk_obj.recv(1024).decode("utf-8"))
sk_obj.sendall(b'ok') # 避免粘
#接受文件名字
file_name=sk_obj.recv(1024).decode("utf-8")
sk_obj.sendall(b'ok')#避免粘包
#接受文件
with open("./%s" %file_name,"wb") as f:
while file_size > 0:
f.write(sk_obj.recv(1024))
file_size-=1024
def post_file(sk_obj,file_path):
"""
发送数据
:param sk_obj: 对象
:param file_path: 文件路径
:return:
"""
#发送文件大小os.stat可以得到文件所有信息
file_size=os.stat(file_path).st_size#获取文件大小
sk_obj.sendall(str(file_size).encode("utf-8"))
sk_obj.recv(1024)#避免粘包
#发送文件名字-分割文件路径
file_name=os.path.split(file_path)[1]
sk_obj.sendall(file_name.encode("utf-8"))
sk_obj.recv(1024) # 避免粘包
#发送文件内容
with open(file_path,"rb") as f:
while file_size > 0:
sk_obj.sendall(f.read(1024))
file_size-=1024
conn,addr=sk.accept()
#接受文件
get_file(conn)
conn.close()
sk.close()