博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python-粘包,切换目录
阅读量:4595 次
发布时间:2019-06-09

本文共 4435 字,大约阅读时间需要 14 分钟。

一.粘包

  只有tcp协议才会发生粘包,udp不会  在tcp协议中:

有一个合包机制(nagle 算法),将多次连续发送且间隔小的数据,将其打包一块数据传送     还有一个机制就是拆包机制,因为受到网卡的MTU限制的数据,进行拆分,拆分成多个小的数据,进行传输     当传输到目标主机的操作系统层时,会重新将多个小的数据合并成原本的数据 为什么udp不会发生粘包?
udp不会发生粘包,udp协议本层对一次收发数据大小的限制是:        65535 - IP包头(20) - udp包头(8) = 65507   站在数据链路层,应为网卡的MTU一般限制在了1500,所以对于数据链路层来说,一次发数据的大小被限制在        1500 - ip包头(20) - udp包头(8) = 1472    得到的结论:        如果sendto(num)        num > 65507 报错        1472 < num < 65507 会在数据链路层拆包,而udp本身就是不可靠的协议,        一旦拆包之后,造成的多个小数据包在网络传输中,如果丢任何一个,那么此次数据传输失败        num < 1472  是比较理想的状态

二.执行命令(subprocess)

cmd = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)# cmd : 代表系统命令# shell = True : 代表这个命令是 系统命令;告诉操作系统,把cmd当成系统命令执行# stdout  : 是执行完系统命令之后,用于保存结果的一个管道# stderr : 是执行完系统命令之后,用于保存错误的一个管道

服务器端:

import socketimport subprocesssk = socket.socket()sk.bind(('127.0.0.1',8080))sk.listen()conn,addr = sk.accept()while 1:    msg_r = conn.recv(1024).decode('utf-8')    result = subprocess.Popen(msg_r,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)    # print(result.stdout.read().decode('gbk'))    # print(result.stderr.read())    stdout = result.stdout.read()    stderr = result.stderr.read()    if  stderr:       conn.send(stderr)    else:        conn.send(stdout)conn.close()sk.close()

 客户端:

'''客户端发送要执行命令服务器执行命令,将执行的结果返回给客户端客户端拿到结果呈现到用户眼前'''import socketsk = socket.socket()sk.connect_ex(('127.0.0.1',8080))while 1:    cmd = input('请输入系统命令>>>')    sk.send(cmd.encode('utf-8'))    msg_r = sk.recv(10240).decode('gbk')    print(msg_r)sk.close()

三.大文件传输

服务器端:

import socketimport jsonimport structsk = socket.socket()sk.bind(('127.0.0.1',8080))sk.listen()conn,addr = sk.accept()# str_dic = conn.recv(100).decode('utf-8')# dic = json.loads(str_dic)# print(dic)b_len_dic = conn.recv(4)len_dic = struct.unpack('i',b_len_dic)[0]str_dic = conn.recv(len_dic).decode('utf-8')dic = json.loads(str_dic)print(dic)# conn.send(b'OK')if dic['opt'] == 'upload':    filename = '1' + dic['filename']    with open(filename,mode='ab') as f:        while dic['filesize']:            content = conn.recv(1024)            f.write(content)            dic['filesize'] -= len(content)conn.close()sk.close()

客户端:

import socketimport osimport jsonimport struct  sk = socket.socket()sk.connect_ex(('127.0.0.1',8080))meau = {
'1':'upload','2':'download'}num = input('请输入选项功能>>>')dic = {
'opt':meau.get(num),'filename':None,'filesize':None}file_path = input('请输入一个绝对路径>>>')filename = os.path.basename(file_path)dic['filename'] = filenamefilesize = os.path.getsize(file_path)dic['filesize'] = filesizestr_dic = json.dumps(dic)len_dic = len(str_dic)b_len_dic = struct.pack('i',len_dic)  # 将字典的长度打包成一个4bytes的数据sk.send(b_len_dic+str_dic.encode('utf-8'))# sk.recv(1024) # 为什么要在这里加上一个recv?主要是防止上一个send程序执行过快,导致下面send程序与其发生粘包,从而发生数据混乱现象with open(file_path,mode='rb') as f: while filesize: content = f.read(1024) sk.send(content) filesize -= len(content)sk.close()

四.切换目录

服务器端:

import socketimport ossk = socket.socket()sk.bind(('127.0.0.1', 8080))sk.listen()conn, addr = sk.accept()def send_data(conn, path):    lis_dir = os.listdir(path)    str_dir = '__'.join(lis_dir)    conn.send(str_dir.encode('utf-8'))abs_path = conn.recv(1024).decode('utf-8')current_dir = abs_pathsend_data(conn, current_dir)while 1:    cmd = conn.recv(1024).decode('utf-8')    if cmd == '..':        current_dir = '/'.join(current_dir.split('\\')[:-1])        print(current_dir)        send_data(conn,current_dir)    else:        filename = cmd.split(' ')[1]        print(filename)        current_dir = current_dir + '//' + filename        print(current_dir)        if os.path.isdir(current_dir):            send_data(conn,current_dir)        else:            conn.send('不是一个文件夹名'.encode('utf-8'))conn.close()sk.close()

客户端:

import socketimport ossk = socket.socket()sk.connect_ex(('127.0.0.1', 8080))abs_path = input('请输入您的根目录>>>')sk.send(abs_path.encode('utf-8'))current_dir = sk.recv(1024).decode('utf-8')print(current_dir.split('__'))while 1:    cmd = input('>>>')    if cmd == '..':        sk.send(cmd.encode('utf-8'))        current_dir = sk.recv(1024).decode('utf-8')        print(current_dir.split('__'))    elif cmd == 'cd':        filename = input('请输入一个文件夹名>>>')        sk.send((cmd+' '+filename).encode('utf-8'))        current_dir = sk.recv(1024).decode('utf-8')        print(current_dir.split('__'))sk.close()

 

转载于:https://www.cnblogs.com/jiujiang/p/11469787.html

你可能感兴趣的文章
2017-12-27练习
查看>>
NET设计规范(二) 命名规范
查看>>
VMware 9.0.1安装Mac OS X Mountain Lion 10.8.2
查看>>
SSL延迟
查看>>
android新手关于左右滑动的问题,布局把<android.support.v4.view.ViewPager/><ImageView/> 放在上面就不行了。...
查看>>
深入理解DIP、IoC、DI以及IoC容器
查看>>
赋值文件
查看>>
Vue 数组 字典 template v-for 的使用
查看>>
蓝牙模块选择经验谈
查看>>
java中==和equals
查看>>
CCActionPageTurn3D
查看>>
python random
查看>>
esp32-智能语音-cli(调试交互命令)
查看>>
netty与MQ使用心得
查看>>
关于dl dt dd 文字过长换行在移动端显示对齐的探讨总结
查看>>
swoolefy PHP的异步、并行、高性能网络通信引擎内置了Http/WebSocket服务器端/客户端...
查看>>
Python学习笔记
查看>>
unshift()与shift()
查看>>
使用 NPOI 、aspose实现execl模板公式计算
查看>>
行为型模式:中介者模式
查看>>