1、UDP通信编解码类

  (1) 类

 # ------------------UDP通信解码编码类------------------------

 from socket import *

 class My_Socket(socket):
def __init__(self,coding='utf-8'):
self.coding = coding
super(My_Socket, self).__init__(type=SOCK_DGRAM) def my_recv(self,num):
msg,addr = self.recvfrom(num)
return msg.decode(self.coding),addr def my_send(self,msg,addr):
return self.sendto(msg.encode(self.coding),addr)

  (2) UDP通信客户端(调用自己的解码编码类)

# --------------UDP通信客户端(调用自己的解码编码类)-----------------

from MySocket import My_Socket

sk = My_Socket()

msg_s = input('>>>')

sk.my_send(msg_s,('127.0.0.1',8080))

sk.close()

UDP通信客户端(调用自己的解码编码类)

  (3) UDP通信服务器端(调用自己的解码编码类)

 # -----------UDP通信服务器端(调用自己的解码编码类)---------------

 from MySocket import My_Socket

 sk = My_Socket()

 sk.bind(('127.0.0.1',8080))

 msg_r,addr = sk.my_recv(1024)

 print(msg_r)

 sk.close()

UDP通信服务器端(调用自己的解码编码类)

2、文件的上传(服务器端)

  (1)只能上传小文件。

 import socket
import json
sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen(5) conn,addr = sk.accept() # 上传下载的逻辑
str_dic = conn.recv(1024).decode('utf-8')
dic = json.loads(str_dic)
# dic = {'opt':ls.get(num),'filename':filename,'content':content}
if dic['opt'] == 'upload':
filename = 'new_'+dic['filename']
with open(filename,'w',encoding='utf-8') as f:
f.write(dic['content']) conn.close()
sk.close()

只能传小文件(服务器端)

  (2)通过方法:先获取文件大小,然后把文件大小加入到字典中,把字典发过去接收端就可以知道文件大小了,就可以根据文件大小进行接收大文件了。
    问题:可能黏包的问题,就是send了字典之后,就send了文件内容。
    解决的方法:在两个send之间加了一个recv,接收一个success 。

 import socket
import json
sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen(5) conn,addr = sk.accept() # 上传下载的逻辑
str_dic = conn.recv(1024).decode('utf-8')# 先接受到字符串形式的字典
conn.send(b'success')# 给客户端回复一个成功,代表字典接收成功了,也是把字典内容和接下来要接收的文件内容分割开
dic = json.loads(str_dic)# 反序列化,将字典还原出来
# dic = {'opt':ls.get(num),'filename':filename,'content':content}
if dic['opt'] == 'upload':
filename = 'new_'+dic['filename']# 产生一个新的文件名
filesize = dic['filesize']# 获取文件的大小
with open(filename,'wb') as f:
while filesize:
content = conn.recv(1024)
filesize -= len(content)# 减去接收到的长度,而不能直接减去1024
f.write(content) conn.close()
sk.close()

以下解决黏包现象,实现大文件的传输,比较low比的方法

  (3)先把字典的大小获取,然后server先接收字典的大小,然后根据字典大小去接收字典,这样就直接解决了2中的问题。

 import socket
import json
sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen(5) conn,addr = sk.accept() # 我算出来了字典长度为70(属于作弊),这个‘70’是两个字节的长度,所以接收两个字节长度,把字典大小接收到
len_dic = int(conn.recv(2).decode('utf-8'))#在这里转成int以便下一行代码中当做recv的参数
# 这个len_dic = 70,转码后是字符串 str_dic = conn.recv(len_dic).decode('utf-8')# 根据字典长度去接收字典,防止接收到文件的内容 # 在这里,上边代码我明确了字典大小,就可以按照字典大小接收固定长度,这样之后,就可以防止上边接收到 下边应该接收的文件内容
# 此时我就可以省略一个 sk.send(b'success')这句话,就可以少一个网络传输数据时的延时。
dic = json.loads(str_dic)
# dic = {'opt':ls.get(num),'filename':filename,'filesize':filesize}
if dic['opt'] == 'upload':
filename = 'new_'+dic['filename']
filesize = dic['filesize']
with open(filename,'wb') as f:
while filesize:
content = conn.recv(1024)
filesize -= len(content)
f.write(content) conn.close()
sk.close()

比较中端的方法

  (4)字典的大小不固定,所以我使用了struct模块中的pack方法,解决这个事情,使字典的大小这个数字无论多少位,我都固定生成一个4位的bytes,这样server端就可以直接先接收4个字节了,通过unpack获取字典大小。

 import socket
import json
import struct
sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen(5) conn,addr = sk.accept() # 上边说了,如果我在这里明确接收2个字节就可以接收到字典的大小,这是作弊
# 因为字典大小如果是 100~999 ,我这里就要接收3个字节
# 如果字典大小是 100000 ~ 999900 ,我这里就要接收6个字节
# 所以为了公正,我使用了struct,在客户端先把‘字典大小’的长度固定为4个字节
len_dic = conn.recv(4)# 此时接收到了 字典的长度,不过是经过struct.pack处理后的
len_str_dic = struct.unpack('i',len_dic)[0] # 在这里,得到int型的字典长度,注意:unpack方法返回一个元组。 str_dic = conn.recv(len_str_dic).decode('utf-8')# 根据字典长度去接收字典,防止接收到文件的内容 dic = json.loads(str_dic)
# dic = {'opt':ls.get(num),'filename':filename,'filesize':filesize}
if dic['opt'] == 'upload':
filename = 'new_'+dic['filename']
filesize = dic['filesize']
with open(filename,'wb') as f:
while filesize:
content = conn.recv(1024)
filesize -= len(content)
f.write(content) conn.close()
sk.close()

比较高端的方法,使用struct

3、远程执行命令

  (1) 远程执行命令(服务器端)

 # ------------------远程执行命令(服务器端)------------------------

 import socket
import subprocess sk = socket.socket()
sk.bind(("127.0.0.1", 8080))
sk.listen(5) conn, addr = sk.accept() while 1:
cmd = conn.recv(1024).decode('utf-8')
r = subprocess.Popen(cmd, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout = r.stdout.read()
stderr = r.stderr.read()
if stdout:
conn.send(stdout)
elif stderr:
conn.send(stderr) conn.close()
sk.close()

远程执行命令(服务器端)

  (2) 远程执行命令(客户端)

 # ---------------远程执行命令(客户端)--------------------

 import socket

 sk = socket.socket()

 sk.connect(('127.0.0.1', 8080))

 while 1:
cmd = input('>>>')
sk.send(cmd.encode('utf-8'))
ret_1 = sk.recv(1024).decode('gbk')
ret_2 = sk.recv(1024).decode('gbk')
print(ret_1) sk.close()

远程执行命令(客户端)

4、黏包

黏包:是指可能是:接收端和发送端两端在进行收发时,数据大小不统一造成的.

也可能是:合包机制和nagle算法的实现,而没有提供科学的拆包机制,造成的.

一种是因为:client连续发送少量数据,时间间隔短,所以nagle算法帮你合包了,但是此时server不知道要接收多少,所以造成数据混乱

一种是因为:client直接发送了大量数据,但是server端接收的长度不够,所以造成数据混乱

  (1) UDP_黏包_服务器

 import socket

 sk = socket.socket(type=socket.SOCK_DGRAM)

 sk.bind(('127.0.0.1', 8080))

 msg, addr = sk.recvfrom(1024)

 print(msg)

 sk.close()

UDP_黏包_客户端

  (2) UDP_黏包_客户端

 import socket
sk = socket.socket(type=socket.SOCK_DGRAM) sk.sendto(b'',('127.0.0.1',8080))
sk.sendto(b'abc',('127.0.0.1',8080))
sk.close()

UDP_黏包_客户端

  (3) TCP_nagle_服务器端

TCP_nagle_服务器端

  (4) TCP_nagle_客户端

 import socket

 BUFSIZE = 1024
ip_port = ('127.0.0.1', 8080) s = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
res = s.connect_ex(ip_port) s.send('hello egg'.encode('utf-8'))

TCP_nagle_客户端

Python_编写UDP通信编解码类、文件的上传、远程执行命令、黏包的更多相关文章

  1. 利用scp 远程上传下载文件/文件夹和ssh远程执行命令

    利用scp传输文件 1.从服务器下载文件scp username@servername:/path/filename /tmp/local_destination例如scp codinglog@192 ...

  2. expect脚本同步文件 expect脚本指定host和要同步的文件 构建文件分发系统 批量远程执行命令

    自动同步文件 #!/usr/bin/expect set " spawn rsync -av root@.txt /tmp/ expect { "yes/no" { se ...

  3. 网络编程 - 1.简单的套接字通信/2.加上通信循环/3.bug修复/4.加上链接循环/5.模拟ssh远程执行命令

    1.简单的套接字通信 服务端 ''' 服务端 接电话 客户端 打电话 1.先启动服务端 2.服务端有两种套接字 1.phone 用来干接收链接的 2.conn 用来干收发消息的 ''' import ...

  4. 使用Struts2实现文件的上传和下载

    (一)单个文件的上传步骤: 1.拷贝jar包:commons-fileupload.jar,  commons-io.jar 下载链接(文件上传.rar):http://www.cnblogs.com ...

  5. 使用xshell软件进行文件的上传和下载

    1.选择xshell的文件里面的属性-->文件传输,把上传路径和下载路径设置好. 上传路径:介绍我们需要向Linux系统里面传东西. 下载路径:就是我们把Linux系统里面的大小拷贝出来. 2. ...

  6. 重新想象 Windows 8.1 Store Apps (89) - 通信的新特性: 下载数据, 上传数据, 上传文件

    [源码下载] 重新想象 Windows 8.1 Store Apps (89) - 通信的新特性: 下载数据, 上传数据, 上传文件 作者:webabcd 介绍重新想象 Windows 8.1 Sto ...

  7. 从零开始编写自己的C#框架(23)——上传组件使用说明

    文章导航 1.前言 2.上传组件功能说明 3.数据库结构 4.上传配置管理 5.上传组件所使用到的类 6.上传组件调用方法 7.效果演示 8.小结 1.前言 本系列所使用的是上传组件是大神July开发 ...

  8. Android中Socket大文件断点上传

    原文:http://blog.csdn.net/shimiso/article/details/8529633 什么是Socket? 所谓Socket通常也称作“套接字”,用于描述IP地址和端口,是一 ...

  9. 使用springmvc进行文件的上传和下载

    文件的上传 SpringMVC支持文件上传组件,commons-fileupload,commons-fileupload依赖commons-io组件 配置步骤说明 第一步:导入包 commons-f ...

随机推荐

  1. UGUI ContentSizeFitter之Button根据Text自适应

    环境 Unity3D 5.3.6f1 练习地址:https://github.com/zhaoqingqing/UGUIDemo  布局放在Layout文件夹 文档:https://docs.unit ...

  2. Servlet(六):连接数据库,完整的CRUD

    Servlet的知识点大致讲完了,今天补充下与之相关的一些小知识,然后做一个完整的小例子. 一.MVC设计模式 1.MVC设计模式是什么? 在了解MVC之前,先聊聊Model1.Model2开发模式. ...

  3. 【转】win2008 中iis7设置404页面但返回状态200的问题解决办法

    今天根据SEO反馈,某个站点中设置的404页面返回的http状态为200.通过站长工具进行查询,发现返回的状态确实为200. 通过彻查问题,发现这个网站的服务器环境为windows2008 服务器为i ...

  4. RPC入门总结(一)RPC定义和原理

    转载:深入浅出 RPC - 浅出篇 转载:RPC框架与Dubbo完整使用 转载:深入浅出 RPC - 深入篇 转载:远程调用服务(RPC)和消息队列(Message Queue)对比及其适用/不适用场 ...

  5. mac下安装redis详细步骤

    Linux下安装redis也可以参照下面的步骤哦!!!! 1.到官网上下载redis,我下载的版本是redis-3.2.5.tar 官网地址:http://redis.io/ 2.将下载下来的tar. ...

  6. Python:Day16 闭包、装饰器

    def outer(): x = 10 def inner(): #条件一.inner就是一个内部函数 print(x) #条件二.引用外部作用域的一个变量,因为x在函数外部的,所以是外部作用域的变量 ...

  7. 微信硬件平台(八) 4 ESP8266通过微信公众号给用户推送消息

    https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=自己申请微信公众号的TOKEN 输出结果:  由于aRDUINO串 ...

  8. Idea突然不停indexing的问题

    只要清理一下Idea的缓存和索引就可以了,在File-Invalidate Caches / Restart中,选择Invalidate and Restart,之后会重启Idea,然后就解决啦!

  9. OpenCV3计算机视觉Python语言实现笔记(四)

    1. Canny边缘检测 OpenCV提供了Canny函数来识别边缘.Canny边缘检测算法有5个步骤:使用高斯滤波器对图像进行去噪.计算梯度.在边缘上使用非最大抑制(NMS).在检测到的边缘上使用双 ...

  10. B. Alyona and a tree

    二分+dfs序+前缀和+瞎几把yy #include "a.h" int n; aLL a; struct edge { int to, nx, w; } e[N << ...