跟着项目做,但是问题有点多,关于网络编程,还没有看,给自己挖个坑,等哔哩哔哩看了再说
这是一个关于tcp传输文件的一个脚本 。
其中问题不少,虽然我解决了不少,但是还有点,留着,等看一遍网络编程,再来看一遍,估计就没什么问题了.
client.py
from socket import *import osimport sysimport jsonimport structfrom optparse import OptionParserdef 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 = 0f = 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') # 获取目标ipparser.add_option('-p', type='string', dest='port', help='specify traget port') # 获取目标端口options, args = parser.parse_args()traget_ip = options.iptraget_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 socketserverimport structimport osimport reimport jsonimport structfrom optparse import OptionParserdef 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_lenclass MyServer(socketserver.BaseRequestHandler):buffsize = 1024def handle(self):print('[+]远程客户机ip',self.client_address[0],'\n')while True: #使用循环是为了让多个客户端连接一个服务端filename = input('请输入需要传输的文件地址>>>').strip() #strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列if(filename == 'exit'):breakhead_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...")
