跟着项目做,但是问题有点多,关于网络编程,还没有看,给自己挖个坑,等哔哩哔哩看了再说
这是一个关于tcp传输文件的一个脚本 。
其中问题不少,虽然我解决了不少,但是还有点,留着,等看一遍网络编程,再来看一遍,估计就没什么问题了.
client.py
from socket import *
import os
import sys
import json
import struct
from optparse import OptionParser
def recv_file(head_dir,tcp_client)
filename = head_dir['filename']
filesize = head_dir['filesize']
print('[+]filename'+filename[0])
print('[+]filesize' +str(filesize[0]))
recv_len = 0
f = open(filename[0],'wb')
while recv_len<filesize:
if(filesize>1024):
recv_mesg = tcp_client.recv(filesize)
recv_mesg + = len(recv_mesg)
f.write(recv_mesg)
else:
recv_mesg = tcp_client.recv(filesize)
recv_mesg + =len(recv_mesg)
f.write(recv_mesg)
f.close()
print("[+]文件传输完毕")
def main():
parser = OptionParser("Usage:%prog -u <traget address> -p <port>") #输出帮助信息
parser.add_option('-u', type='string', dest='ip', help='specify traget ip') # 获取目标ip
parser.add_option('-p', type='string', dest='port', help='specify traget port') # 获取目标端口
options, args = parser.parse_args()
traget_ip = options.ip
traget_port = int(options.port)
# print(traget_ip,traget_port)
tcp_client= socket(AF_INET, SOCK_STREAM) #socket 初始化 不要将文件名和socket相同
ip_port = ((traget_ip, traget_port))
print("[+]正在尝试链接")
tcp_client.connect(ip_port) # connect_ex 和 connect差不多
print("[+]等待服务端应答")
struct_len=tcp_client.recv(4) #定义接受长度
struct_info_len = struct.unpack('i',struct_len)[0] #解析得到报头信息长度
print("[+]接受报头长度为:"+ str(struct_info_len) )
head_info=tcp_client.recv(struct_info_len)
head_dir = json.loads(head_info.decode('utf-8')) # 将报头反序列化
print("[+]报头内容为:"+str(head_dir) )
recv_file(head_dir,tcp_client)
if __name__=='__main__':
try:
main()
except keyboardInterrupt:
print("interrupted by user,killing all threads..")
server.py
import socketserver
import struct
import os
import re
import json
import struct
from optparse import OptionParser
def SendFile(conn, head_info,head_info_len,filename): #发送文件
try:
conn.send(head_info_len) # send 发送
conn.send(head_info.encoding('utf-8'))
with open(filename,'rb') as f:
conn.sendall(f.read()) # sendall 发送所有读出的文件
print('[+]send success!'+filename)
except:
print('send failes' + filename)
def operafile(filename): #返回文件名和文件大小
filesize = os.path.getsize(filename)
pattern = re.compile(r'([^<>/\\\|:""\*\?]+\.\w+$)')
data = pattern.findall(filename)
head_dir ={
'filename': data ,
'filesize': filesize
}
head_info = json.dump(head_dir) # 将数据结构更改为json格式
head_info_len = struct.pack('i',len(head_info)) # 将数据转换为字节流 格式符”i”表示转换为int,’ii’表示有两个int变量
return head_info,head_info_len
class MyServer(socketserver.BaseRequestHandler):
buffsize = 1024
def handle(self):
print('[+]远程客户机ip',self.client_address[0],'\n')
while True: #使用循环是为了让多个客户端连接一个服务端
filename = input('请输入需要传输的文件地址>>>').strip() #strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列
if(filename == 'exit'):
break
head_info,head_info_len = operafile(filename)
sendFile(self.request,head_info,head_info_len,filename)
self.request.close()
def main():
parser=OptionParser("Usage:prog -p <port>")
parser.add_option('-p', type='string', dest='port', help='specify targer port' ) #获取监听端口
options , args =parser.parse_args()
port = int(options.port) #需要指定为int,不然会报错
print('[+]正在监听'+str(port))
s = socketserver.ThreadingTCPServer(('0.0.0.0', port), MyServer)
#ThreadingTCPServer,就是线程化的TCP服务器,客户端发起的TCP连接,在服务器侧,都是一个个的线程。显然,这个ThreadingTCPServer是异步多线程的框架模型
s.serve_forever()
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("interrupted by user, killing all threads...")