python3 socket实操备忘
server端:
#!/usr/bin/env python3
# 网络编程:三要素:ip地址、端口(进程)、协议
# socket.socket(socket_family,socket_type,protocal=0)
# socket_family 可以是 AF_UNIX(unix使用) 或 AF_INET(ipv4)、AF_INET6(ipv6)。socket_type 可以是 SOCK_STREAM(tcp协议) 或 SOCK_DGRAM(udp协议)。protocol 一般不填,默认值为 0。
import socket
import subprocess
import os
BaseDir = os.path.dirname(os.path.abspath(__file__))
sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 创建通道:套接字
address = ("127.0.0.1",8000)
sk.bind(address) # 设置服务器ip地址及端口:绑定(主机,端口号)到套接字,元组
sk.listen(2) # 设置最大排队人数
while True:
conn,addr = sk.accept() # 等待连接。。。waiting....被动接受TCP客户的连接,(阻塞式)等待连接的到来
try:
data = conn.recv(1024) # recv不允许接收空数据。当断开链接时,data = "",接收数据中。。。waiting
except Exception as e: # 获取数据失败-出错时,断开连接
break
# print(conn,addr)
data = str(data,"utf-8")
#********** 聊天 **********
if data == "chat":
while True:
try:
data = conn.recv(1024) # recv不允许接收空数据。当断开链接时,data = "",接收数据中。。。waiting
except Exception as e: # 获取数据失败-出错时,断开连接
break
if not data:
conn.close()
print("正常连接关闭!")
break
print("....",str(data,"utf-8"))
inp = input(">>>")
conn.send(bytes(inp,"utf-8"))
#********** 远程命令 **********
elif data == "remote_control":
while True:
try:
data = conn.recv(1024) # recv不允许接收空数据。当断开链接时,data = "",接收数据中。。。waiting
except Exception as e: # 获取数据失败-出错时,断开连接
break
if not data:
conn.close()
print("正常连接关闭!")
break
# print("....",str(data,"utf-8"))
# subprocess 执行str(data,"utf-8")这个命令。通过stdout = subprocess.PIPE把结果调回主进程。shell = True必填
obj = subprocess.Popen(str(data,"utf-8"), shell = True, stdout = subprocess.PIPE)
cmd_result = obj.stdout.read() # 获取cmd在本机执行的结果,bytes()类型,系统编码
print(type(cmd_result)) # 调试,确定类型为bytes()类型
print(cmd_result)
result_len = bytes(str(len(cmd_result)),"utf-8") # 取得结果长度,并转成bytes类型
conn.sendall(result_len) # 把结果长度发送给客户端,连续发送2信息,linux出错。粘包现象!
conn.recv(1024) # 解决粘包现象,中间穿插一个等待。client发送随机内容
conn.sendall(cmd_result) # 把结果发送给客户端
#********** 上传文件 **********
elif data == "post_file":
while True:
try:
data = conn.recv(1024) # recv不允许接收空数据。当断开链接时,data = "",接收数据中。。。waiting
except Exception as e: # 获取数据失败-出错时,断开连接
break
if not data:
conn.close()
print("正常连接关闭!")
break
data = data.decode("utf-8")
# print(data)
cmd, filename, filesize = data.split("|")
abspath = os.path.join(BaseDir,"img",filename) # 路径拼接
filesize = int(filesize) # 把接收到的filesize转成整形
# print(abspath)
if cmd == "post":
with open(abspath,"ab") as f:
recv_data = 0
while recv_data != filesize:
data = conn.recv(1024)
f.write(data)
recv_data += len(data)
print("上传成功!")
sk.close()
client端:
#!/usr/bin/env python3
import socket
import re
import os
BaseDir = os.path.dirname(os.path.abspath(__file__))
sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
address = ("127.0.0.1",8000)
for i in range(3):
try:
sk.connect(address)
except Exception as e:
i += 1
else:
break
inp = input(">>>")
if inp == "exit":
sk.close()
else:
sk.send(bytes(inp,"utf-8"))
if inp == "chat": # 聊天
while True:
inp = input(">>>")
if inp == "exit":
break
sk.send(bytes(inp,"utf-8"))
data = sk.recv(1024)
print(str(data,"utf-8"))
else:
sk.close()
elif inp == "remote_control": # 远程命令
while True:
inp = input(">>>")
if inp == "exit":
break
sk.send(bytes(inp,"utf-8"))
data_len = sk.recv(1024) # 取得文件长度,bytes()类型
data_len = int(str(data_len,"utf-8")) # 取得bytes()数据的长度。整形
# print(data_len) # 调式
sk.send(b"111")
data_recv = bytes() # 定义一个空的bytes类型
while len(data_recv) != data_len: # bytes()类型,长度比较
data = sk.recv(1024)
data_recv += data
print(str(data_recv,"utf-8"))
else:
sk.close()
elif inp == "post_file": # 上传文件
while True:
inp = input(">>>") # 上传文件格式:post|文件路径
if inp == "exit":
break
# elif re.findall(r"post/d*|/d*.*",inp):
cmd, path = inp.split("|") # 取得命令及相对路径
cmd = cmd.strip()
path = path.strip()
abspath = os.path.join(BaseDir,path) # 获得绝对路径
filename = os.path.basename(abspath) # 取得文件名
filesize = os.stat(abspath).st_size # 取得文件大小,其实是byte()类型的长度,整数
fileinfo = "%s|%s|%s"%(cmd,filename,filesize) # 信息打包
print(fileinfo) # str类型
sk.sendall(bytes(fileinfo,"utf-8")) # 发送打包的信息
import time # linux下的粘包问题
time.sleep(1)
with open(abspath,"rb") as f: # 以bytes()格式打开文件
send_data = 0
while send_data != filesize:
data = f.read(1024)
sk.sendall(data)
send_data += len(data)

浙公网安备 33010602011771号