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. UICollectionView 基础

    在iOS开发中经常会用到UICollectionView,和UITableView同样即成UIScrollView 但是操作起来比UITableVIew要麻烦一些 ,有些地方需要注意,一下是UICol ...

  2. sed:-e 表达式 #1,字符 10:未终止的“s”命令

    执行shell脚本时,使用sed变量替换指定的字符串,一直出现这个错误: [root@bqh-118 scripts]# vim while_rz.sh [root@bqh-118 scripts]# ...

  3. 使用 cmd连接 Oracle,MySql,SQL Server 数据库

    1. Oracle cmd连接数据库 语法: sqlplus 用户/口令(密码)@服务器IP/数据库实例名(SID) 1.1 方式一 数据库服务在本机上IP可以用localhost替换 sqlplus ...

  4. February 11th, 2018 Week 7th Sunday

    Grasp all, lose all. 欲尽得,必尽失. Not to be greedy and not to try to get everything. Our time, energy an ...

  5. zTree获取当前节点的下一级子节点数

    使用zTree插件实现树形图中,需要获取当前点击的父节点的子节点数的需求,使用treeNode.children获取子节点数据集合,使用length方法获取集合长度.将当前节点的treeNode传入即 ...

  6. C#基础知识之托管代码和非托管代码

    什么是托管代码(managed code)? 托管代码(Managed Code)就是中间语言(IL)代码,在公共语言运行库(CLR)中运行.编译器把代码编译成中间语言,当方法被调用时,CLR把具体的 ...

  7. 忽略Git钩子

    https://blog.csdn.net/alps1992/article/details/80464700 pre-commit GIT_DIR/hooks/pre-commit 这个钩子被 gi ...

  8. Loj 3058. 「HNOI2019」白兔之舞

    Loj 3058. 「HNOI2019」白兔之舞 题目描述 有一张顶点数为 \((L+1)\times n\) 的有向图.这张图的每个顶点由一个二元组 \((u,v)\) 表示 \((0\le u\l ...

  9. 自定义的库加载不进来,因为库中import的PIL和pillow文件没有pip install

    1.自定义的库,加载进来,提示red不能识别这个class或moudle 2.应该展开细节多看下,细节中提示,没有PIL和pillow 3.这个时候在cmd中使用pip安装PIL和pillow pip ...

  10. oracle 创建表空间TABLESPACE

    题外话: 在oracle中,我们的数据库用户都有一个默认表空间归属,当在该用户下创建表或其他对象时默认会将其归属在默认表空间: 不排除后期修改了用户默认表空间的情况存在,此后新加入的对象默认会放置在新 ...