Python中的Socket 与 ScoketServer 通信及遇到问题解决方法


Posted in Python onApril 01, 2019

Socket有一个缓冲区,缓冲区是一个流,先进先出,发送和取出的可自定义大小的,如果取出的数据未取完缓冲区,则可能存在数据怠慢。其中【recv(1024)】表示从缓冲区里取最大为1024个字节,但实际取值大小是不确定的,推荐其值小于等于8192。

黏包问题:

Socket发送两条连续数据时,可能最终会拼接成一条进行发送

解决方法一:

两条数据间进行延时发送,如【tiem.sleep(0.5) #延时0.5s】

解决方法二:

每次发送后等待对方确认接收信息数据,发送一条后就立即接收等待

解决方法三:

设定接收数据大小,发送端每次发送需要发送的数据的数据大小,接收端通过设置【recv(xx)】只接收确定的大小

Socket基本使用:

简单的服务器:

import socket
sser=socket.socket()#得到socket对象
sser.bind(("0.0.0.0",2699))#建立监听
sser.listen(3)
print("等等客户端连接")
conn,addr=sser.accept() #等待连接,会一直处于阻塞,返回连接对象和对方地址
print("有客户端已经连接,IP地址和端口为:",addr)
#接收数据,会一直阻塞,建议低于8192
#使用连接对象操作
rdata=conn.recv(1024)
print(rdata.decode("gbk"))
conn.send("服务器返回,收到数据".encode("gbk"))#发送数据,使用连接对象操作
#关闭连接
sser.close()

简单的客户端:

import socket
sclient=socket.socket()#得到socket对象
#连接服务器
#失败会报错:ConnectionRefusedError
sclient.connect(("192.168.1.135",2699))
sclient.send("东小东".encode("gbk"))#发送数据
#接收数据,会一直阻塞,建议低于8192
rdata=sclient.recv(1024)
print(rdata.decode("gbk"))
#关闭连接
sclient.close()

Soket进阶:

服务器进阶:

实现客户循环连接及数据循环收发和判断客户端是否断开

import socket
sser=socket.socket()#得到socket对象
sser.bind(("0.0.0.0",2699))#建立监听
sser.listen(3)
while True:
  print("等等客户端连接")
  conn,addr=sser.accept() #等待连接,会一直处于阻塞,返回连接对象和对方地址
  print("有客户端已经连接,IP地址和端口为:",addr)
  conn.send(("服务器欢迎你:%s\r\n"%(str(addr))).encode("gbk")) # 发送数据,使用连接对象操作
  while True:
    #接收数据,会一直阻塞
    #使用连接对象操作
    rdata=conn.recv(1024)
    if not rdata: break #判断客户端是否断开,断开则收到空数据
    print(rdata.decode("gbk"))
    conn.send("服务器返回,收到数据\r\n".encode("gbk"))#发送数据,使用连接对象操作
#关闭连接
sser.close()

客户端进阶:

实现循环收发和判断服务器是否断开

import socket
sclient=socket.socket()#得到socket对象
#连接服务器
#失败会报错:ConnectionRefusedError
sclient.connect(("192.168.1.135",2699))
while True:
 #接收数据,会一直阻塞
 rdata=sclient.recv(1024)
 if not rdata: break # 判断服务器是否断开,断开则收到空数据
 print(rdata.decode("gbk"))
 sclient.send(("客户端收到数据:%s\r\n"%rdata.decode("gbk")).encode("gbk")) # 发送数据
#关闭连接
sclient.close()

注意:

发送数据不可发送空字符,否则会卡住,解决方法为判断输入的是否为空值,空值则进行数据发送

strx=input("输入:").strip()#得到控制台输入值
if(len(strx)==0):continue #如果为空字符,则跳出本次循环
print(strx) #打印
sclient.send(strx.encode("gbk")) # 发送数据

发送大数据:

先发送总体数据大小,socket另一端判断实际接收的数据大小与总数据大小进行比较,循环recv()进行数据接收

 简单的ssh实现:

服务端:

import os
import socket
sser=socket.socket()#得到socket对象
sser.bind(("0.0.0.0",2697))#建立监听
sser.listen(3)
while True:
  print("等等客户端连接")
  conn,addr=sser.accept() #等待连接,会一直处于阻塞,返回连接对象和对方地址
  print("有客户端已经连接,IP地址和端口为:",addr)
  conn.send(("服务器欢迎你:%s\r\n"%(str(addr))).encode("gbk")) # 发送数据,使用连接对象操作
  while True:
    #接收数据,会一直阻塞
    rdata=conn.recv(1024)
    if not rdata: break #判断客户端是否断开,断开则收到空数据
    sendtox=os.popen(rdata.decode("gbk")).read() #执行命令
    conn.send(str(len(sendtox)).encode("gbk")) #发送执行命令的结果长度
    #如果长度大于0 则发送命令结果数据
    if len(sendtox)>0:
    if conn.recv(10).decode("gbk")=="1":
     conn.sendall(sendtox.encode("gbk"))#发送最终数据
#关闭连接
sser.close()

客户端:

import socket
sclient=socket.socket()#得到socket对象
#连接服务器
#失败会报错:ConnectionRefusedError
sclient.connect(("192.168.43.21",2697))
# 接收数据,会一直阻塞
rdata = sclient.recv(1024)
print(rdata.decode("gbk"))
while True:
 strx = input("请输入命令:").strip() # 得到控制台输入值
 if (len(strx) == 0): continue # 如果为空字符,则跳出本次循环
 sclient.send(strx.encode("gbk")) # 发送数据
 rdata = sclient.recv(10)
 if not rdata: break # 判断服务器是否断开,断开则收到空数据
 #判断命令是否执行成功,0为失败
 dataall=int(rdata.decode("gbk"))
 if dataall==0:
  continue
 sclient.send("1".encode("gbk")) # 发送确认接收数据命令
 #循环接收数据
 datanew=0
 while dataall !=datanew:
  rdata=sclient.recv(1024).decode("gbk")
  datanew+=len(rdata)
  print(rdata)
#关闭连接
sclient.close()

发送文件:

发送文件,使用read()读取文件数据后,可循环调用send()发送数据,或者使用sendall()一次性发送所有数据,socket另一端接收可循环recv()进行数据接收,且每次接收的数据大小是不确定的。文件传输需要验证发送和接受的数据是否完全一致,可以通过数据大小加md5双重验证,发送端:md5在每次发送一条数据时进行update(),在数据发送完成后再发送md5值;接受端:md5在每次接收到一条数据后进行update(),在文件接收完成后再接收发送端发送的md5值,将两值进行比较,相同则表示传输无丢包,但加入md5校验,将会影响传输速率。

发送文件数据:先发送总体数据大小,socket另一端判断实际接收的数据大小与总数据大小进行比较,循环recv()进行数据接收

示例:客户端发送文件名,服务器判断文件是否存在,如果不存在或者是空文件则不进行传输,服务器进行文件发送,客户端实现文件接收

服务器

import os
import socket
sser=socket.socket()#得到socket对象
sser.bind(("0.0.0.0",2697))#建立监听
sser.listen(3)
while True:
  print("等等客户端连接")
  conn,addr=sser.accept() #等待连接,会一直处于阻塞,返回连接对象和对方地址
  print("有客户端已经连接,IP地址和端口为:",addr)
  conn.send(("服务器欢迎你:%s\r\n"%(str(addr))).encode("gbk")) # 发送数据,使用连接对象操作
  while True:
    #接收数据,会一直阻塞
    rdata=conn.recv(1024)
    if not rdata: break #判断客户端是否断开,断开则收到空数据
    filesize=0
    filenamex=rdata.decode("gbk")
    if os.path.isfile(filenamex): #判断是否是文件
     filesize=os.stat(filenamex).st_size #得到文件大小
    conn.send(str(filesize).encode("gbk")) #不是文件则发送0,是文件则是实际大小
    #如果文件大小大于0 则发送文件
    if filesize>0:
    if conn.recv(10).decode("gbk")=="1": #等待确认接收命令
     #一行一行发送数据
     f=open(filenamex,"rb")
     for linex in f:
      conn.sendall(linex)#发送最终数据
#关闭连接
sser.close()

客户端

import socket
sclient=socket.socket()#得到socket对象
#连接服务器
#失败会报错:ConnectionRefusedError
sclient.connect(("192.168.43.21",2697))
# 接收数据,会一直阻塞
rdata = sclient.recv(1024)
print(rdata.decode("gbk"))
while True:
 filenamex = input("请输入文件名:").strip() # 得到控制台输入值
 if (len(filenamex) == 0): continue # 如果为空字符,则跳出本次循环
 sclient.send(filenamex.encode("gbk")) # 发送数据
 rdata = sclient.recv(10)
 if not rdata: break # 判断服务器是否断开,断开则收到空数据
 #判断命令是否执行成功,0为失败
 dataall=int(rdata.decode("gbk"))
 if dataall==0:
  print("文件不存在或者为空")
  continue
 sclient.send("1".encode("gbk")) # 发送确认接收数据命令
 #打开文件
 f=open(filenamex,"wb")
 #循环接收数据
 datanew=0
 while dataall !=datanew:
  rdata=sclient.recv(1024)
  datanew+=len(rdata)
  f.write(rdata)
 print("文件(%s)接收完毕"%filenamex)
 f.close() #关闭文件
#关闭连接
sclient.close()

ScoketServer

服务端实现多并发效果,可以同时接入多个客户端

import socketserver
#建立一个类,必须继承 socketserver.BaseRequestHandler 类
class DongSocket(socketserver.BaseRequestHandler):
 #必须重写handle方法
 def handle(self):
  print("建立新连接,对方地址为:{}".format(self.client_address))
  while True:
   try:
    self.datax=self.request.recv(1024).decode("gbk") #接收数据
    print("接收的数据为:%s"%self.datax)
    self.request.send(("服务器返回数据:%s"%self.datax).encode("gbk"))
   except Exception as e:
    print("断开,再见:{}".format(self.client_address))
    break
#参数:(("ip",端口),自定义类)
#ss=socketserver.TCPServer(("0.0.0.0",2351),DongSocket) #与之前的socket服务器效果一致,同时只能连接一个客户端
ss=socketserver.ThreadingTCPServer(("0.0.0.0",2351),DongSocket) #同时可以连接多个客户端,多并发
ss.serve_forever()

总结

以上所述是小编给大家介绍的Python中的Socket 与 ScoketServer 通信及遇到问题解决方法 ,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
详解Python使用simplejson模块解析JSON的方法
Mar 24 Python
python itchat实现微信好友头像拼接图的示例代码
Aug 14 Python
Python中类的初始化特殊方法
Dec 01 Python
python3+selenium实现126邮箱登陆并发送邮件功能
Jan 23 Python
PyQt5内嵌浏览器注入JavaScript脚本实现自动化操作的代码实例
Feb 13 Python
python实现最大优先队列
Aug 29 Python
Centos7下源码安装Python3 及shell 脚本自动安装Python3的教程
Mar 07 Python
tensorflow模型文件(ckpt)转pb文件的方法(不知道输出节点名)
Apr 22 Python
TensorFlow实现模型断点训练,checkpoint模型载入方式
May 26 Python
Pytorch之Tensor和Numpy之间的转换的实现方法
Sep 03 Python
使用Python Tkinter实现剪刀石头布小游戏功能
Oct 23 Python
FP-growth算法发现频繁项集——构建FP树
Jun 24 Python
python assert的用处示例详解
Apr 01 #Python
使用Python操作FTP实现上传和下载的方法
Apr 01 #Python
Python提取特定时间段内数据的方法实例
Apr 01 #Python
如何使用Python进行OCR识别图片中的文字
Apr 01 #Python
Python datetime和unix时间戳之间相互转换的讲解
Apr 01 #Python
详解Python网络框架Django和Scrapy安装指南
Apr 01 #Python
详解python的argpare和click模块小结
Mar 31 #Python
You might like
Terran历史背景
2020/03/14 星际争霸
建立文件交换功能的脚本(一)
2006/10/09 PHP
php中用文本文件做数据库的实现方法
2008/03/27 PHP
php图片验证码代码
2008/03/27 PHP
PHP中的MYSQL常用函数(php下操作数据库必备)
2010/09/12 PHP
laravel框架分组控制器和分组路由实现方法示例
2020/01/25 PHP
PHP Web表单生成器案例分析
2020/06/02 PHP
WEB 浏览器兼容 推荐收藏
2010/05/14 Javascript
拉动滚动条加载数据的jquery代码
2012/05/03 Javascript
说说JSON和JSONP 也许你会豁然开朗
2012/09/02 Javascript
JavaScript显示当然日期和时间即年月日星期和时间
2013/10/29 Javascript
JS执行删除前的判断代码
2014/02/18 Javascript
jQuery级联操作绑定事件实例
2014/09/02 Javascript
jQuery+css实现的换页标签栏效果
2016/01/27 Javascript
jQuery插件制作的实例教程
2016/05/16 Javascript
EXT中单击button按钮grid添加一行(光标位置可设置)的实例代码
2016/06/02 Javascript
angular基于路由控制ui-router实现系统权限控制
2016/09/27 Javascript
Webpack打包慢问题的完美解决方法
2017/03/16 Javascript
使用jQuery实现页面定时弹出广告效果
2017/08/24 jQuery
NVM安装nodejs的方法实用步骤
2019/01/16 NodeJs
js获取form表单中name属性的值
2019/02/27 Javascript
[01:33]真香警告!DOTA2勇士令状不朽珍藏Ⅱ饰品欣赏
2018/06/26 DOTA
Python使用multiprocessing创建进程的方法
2015/06/04 Python
python中import学习备忘笔记
2017/01/24 Python
Python类绑定方法及非绑定方法实例解析
2020/10/09 Python
Anaconda的安装与虚拟环境建立
2020/11/18 Python
Python 求向量的余弦值操作
2021/03/04 Python
俄罗斯花园种植材料批发和零售网上商店:Беккер
2019/07/22 全球购物
斯洛伐克家具和时尚装饰品购物网站:Butlers.sk
2019/09/08 全球购物
Talbots官网:美国成熟女装品牌
2019/11/15 全球购物
Sunglass Hut巴西网上商店:男女太阳镜
2020/10/04 全球购物
2015年世界粮食日演讲稿
2015/03/20 职场文书
大学生创业计划书常用模板
2019/08/07 职场文书
Python基础详解之邮件处理
2021/04/28 Python
唤醒紫霞仙子,携手再游三界!大话手游X《大话西游》电影合作专属剧情任务
2022/04/03 其他游戏
GO语言异常处理分析 err接口及defer延迟
2022/04/14 Golang