socket补充:通信循环、链接循环、远程操作及黏包现象

socket补充:通信循环、链接循环、远程操作及黏包现象

socket通信循环

server端:

import socketphone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)phone.bind(('127.0.0.1',8080))phone.listen(5)conn, client_addr = phone.accept()
print(conn, client_addr, sep='\n')while 1:  # 循环收发消息try:from_client_data = conn.recv(1024)print(from_client_data.decode('utf-8'))conn.send(from_client_data + b'SB')except ConnectionResetError:breakconn.close()
phone.close()

client端:

import socketphone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 买电话phone.connect(('127.0.0.1',8080))  # 与客户端建立连接, 拨号while 1:  # 循环收发消息client_data = input('>>>')phone.send(client_data.encode('utf-8'))from_server_data = phone.recv(1024)print(from_server_data.decode('utf-8'))phone.close()  # 挂电话

socket通信链接循环

server端:

import socketphone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)phone.bind(('127.0.0.1',8080))phone.listen(5)while 1 : # 循环连接客户端conn, client_addr = phone.accept()print(client_addr)while 1:try:from_client_data = conn.recv(1024)print(from_client_data.decode('utf-8'))conn.send(from_client_data + b'SB')except ConnectionResetError:breakconn.close()
phone.close()

服务端:

import socketphone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 买电话phone.connect(('127.0.0.1',8080))  # 与客户端建立连接, 拨号while 1:client_data = input('>>>')phone.send(client_data.encode('utf-8'))from_server_data = phone.recv(1024)print(from_server_data.decode('utf-8'))phone.close()  # 挂电话

socket远程操作

import subprocessobj = subprocess.Popen('dir1',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,)print(obj.stdout.read().decode('gbk'))  # 正确命令
print(obj.stderr.read().decode('gbk'))  # 错误命令

服务端:

import socket
import subprocess
phone = socket.socket()phone.bind(('127.0.0.1',8848))phone.listen(2)
# listen: 2 允许有两个客户端加到半链接池,超过两个则会报错while 1:conn,addr = phone.accept()  # 等待客户端链接我,阻塞状态中print(f'链接来了: {conn,addr}')while 1:try:from_client_data = conn.recv(1024)  # 最多接受1024字节if from_client_data.upper() == b'Q':print('客户端正常退出聊天了')breakobj = subprocess.Popen(from_client_data.decode('utf-8'),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,)result = obj.stdout.read() + obj.stderr.read()conn.send(result)except ConnectionResetError:print('客户端链接中断了')breakconn.close()
phone.close()# shell: 命令解释器,相当于调用cmd 执行指定的命令。
# stdout:正确结果丢到管道中。
# stderr:错了丢到另一个管道中。
# windows操作系统的默认编码是gbk编码。

客户端:

import socketphone = socket.socket()phone.connect(('127.0.0.1',8848))
while 1:to_server_data = input('>>>输入q或者Q退出').strip().encode('utf-8')if not to_server_data:# 服务端如果接受到了空的内容,服务端就会一直阻塞中,所以无论哪一端发送内容时,都不能为空发送print('发送内容不能为空')continuephone.send(to_server_data)if to_server_data.upper() == b'Q':breakfrom_server_data = phone.recv(1024)  # 最多接受1024字节print(f'{from_server_data.decode("gbk")}')phone.close()

什么叫做黏包现象?为什么会出现黏包现象?

socket收发消息的原理

1729998-20190816152859172-18357743.png

应用程序所看到的数据是一个整体,或说是一个流(stream),一条消息有多少字节对应用程序是不可见的,因此TCP协议是面向流的协议,这也是容易出现粘包问题的原因。

而UDP是面向消息的协议,每个UDP段都是一条消息,应用程序必须以消息为单位提取数据,不能一次提取任意字节的数据,这一点和TCP是很不同的。怎样定义消息呢?

可以认为对方一次性write/send的数据为一个消息,需要明白的是当对方send一条信息的时候,无论底层怎样分段分片,TCP协议层会把构成整条消息的数据段排序完成后才呈现在内核缓冲区。

设置缓冲区的两个好处:

  1. 暂时存储一些数据.
  2. 缓冲区存在如果你的网络波动,保证数据的收发稳定,匀速.

所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。

只有TCP有粘包现象,UDP永远不会粘包

黏包的两种情况:

1,接收方没有及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)

server端:

import socket
import subprocessphone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)phone.bind(('127.0.0.1', 8080))phone.listen(5)while 1:  # 循环连接客户端conn, client_addr = phone.accept()print(client_addr)while 1:try:cmd = conn.recv(1024)ret = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)correct_msg = ret.stdout.read()error_msg = ret.stderr.read()conn.send(correct_msg + error_msg)except ConnectionResetError:breakconn.close()
phone.close()

client端:

import socketphone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 买电话phone.connect(('127.0.0.1',8080))  # 与客户端建立连接, 拨号while 1:cmd = input('>>>')phone.send(cmd.encode('utf-8'))from_server_data = phone.recv(1024)print(from_server_data.decode('gbk'))phone.close()

2、发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据也很小,会合到一起,产生粘包)

server端:

import socketphone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)phone.bind(('127.0.0.1', 8080))phone.listen(5)conn, client_addr = phone.accept()frist_data = conn.recv(1024)
print('1:',frist_data.decode('utf-8'))  # 1: helloworld
second_data = conn.recv(1024)
print('2:',second_data.decode('utf-8'))conn.close()
phone.close()

客户端:

import socketphone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  phone.connect(('127.0.0.1', 8080)) phone.send(b'hello')
phone.send(b'world')phone.close()  # 两次返送信息时间间隔太短,数据小,造成服务端一次收取

如何解决黏包现象?

struct模块

该模块可以把一个类型,如数字,转成固定长度的bytes

1729998-20190816152911745-450888539.jpg

import struct
# 将一个数字转化成等长度的bytes类型。
ret = struct.pack('i', 183346)
print(ret, type(ret), len(ret))# 通过unpack反解回来
ret1 = struct.unpack('i',ret)[0]
print(ret1, type(ret1), len(ret1))# 但是通过struct 处理不能处理太大ret = struct.pack('l', 4323241232132324)
print(ret, type(ret), len(ret))  # 报错

方案一:low版。

  问题的根源在于,接收端不知道发送端将要传送的字节流的长度,所以解决粘包的方法就是围绕,如何让发送端在发送数据前,把自己将要发送的字节流总数按照固定字节发送给接收端后面跟上总数据,然后接收端先接收固定字节的总字节流,再来一个死循环接收完所有数据。

server端:

import socket
import subprocess
import struct
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)phone.bind(('127.0.0.1', 8080))phone.listen(5)while 1:conn, client_addr = phone.accept()print(client_addr)while 1:try:cmd = conn.recv(1024)ret = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)correct_msg = ret.stdout.read()error_msg = ret.stderr.read()# 1 制作固定报头total_size = len(correct_msg) + len(error_msg)header = struct.pack('i', total_size)# 2 发送报头conn.send(header)# 发送真实数据:conn.send(correct_msg)conn.send(error_msg)except ConnectionResetError:breakconn.close()
phone.close()

client端:

import socket
import struct
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)phone.connect(('127.0.0.1',8080))while 1:cmd = input('>>>').strip()if not cmd: continuephone.send(cmd.encode('utf-8'))# 1,接收固定报头header = phone.recv(4)# 2,解析报头total_size = struct.unpack('i', header)[0]# 3,根据报头信息,接收真实数据recv_size = 0res = b''while recv_size < total_size:recv_data = phone.recv(1024)res += recv_datarecv_size += len(recv_data)print(res.decode('gbk'))phone.close()

转载于:https://www.cnblogs.com/lifangzheng/p/11364213.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/247134.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java生鲜电商平台-SpringCloud微服务架构中核心要点和实现原理

Java生鲜电商平台-SpringCloud微服务架构中核心要点和实现原理 说明&#xff1a;Java生鲜电商平台中&#xff0c;我们将进一步理解微服务架构的核心要点和实现原理&#xff0c;为读者的实践提供微服务的设计模式&#xff0c;以期让微服务在读者正在工作的项目中起到积极的作用。…

ASP.NET Core Web 应用程序开发期间部署到IIS自定义主机域名并附加到进程调试

想必大家之前在进行ASP.NET Web 应用程序开发期间都有用到过将我们的网站部署到IIS自定义主机域名并附加到进程进行调试。 那我们的ASP.NET Core Web 应用程序又是如何部署到我们的IIS上面进行调试的呢&#xff0c;接下来我们来简单介绍下&#xff1a; 一、安装IIS所需的Host扩…

ASP.NET Core Web 应用程序系列(一)- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入(MVC当中应用)...

在正式进入主题之前我们来看下几个概念&#xff1a; 一、依赖倒置 依赖倒置是编程五大原则之一&#xff0c;即&#xff1a; 1、上层模块不应该依赖于下层模块&#xff0c;它们共同依赖于一个抽象。 2、抽象不能依赖于具体&#xff0c;具体依赖于抽象。 其中上层就是指使用者&am…

苹果电脑基本设置+Linux 命令+Android 实战集锦

本文微信公众号「AndroidTraveler」首发。 背景 大多数应届毕业生在大学期间使用的比较多的是 windows 电脑&#xff0c;因此初入职场如果拿到一台苹果电脑&#xff0c;可能一时间不能够很快的上手。基于此&#xff0c;这边出了系列视频&#xff0c;通过实际的演示让没使用过苹…

Mac中AndroidStudio没有找到Plugins的问题

我们在windows中都可以正常找到plugins 但是在Mac上AndroidStudio里 setting打开却没有plugins 正准备在Mac上搞一下flutter呢 我感觉智商受到了侮辱&#xff01; 这里其实是mac版本给我开了个玩笑 你可以按快捷键&#xff0c;你就可以找到 快捷键 command ‘,’ 没错就是comm…

进程和操作系统概述

进程和操作系统概述 进程的基础 程序和进程&#xff1a; 程序是一对静态的代码文件 进程是一个正在运行着的程序&#xff0c;抽象概念 进程由操作系统操控调用交于CPU运行 操作系统 1.管理控制协调计算机硬件和软件的关系 2.操作系统的作用&#xff1f; ​ 第一个作用&#xff…

对前端Jenkins自动化部署的研究

1. 安装 安装 Nginx 1.1去官网下直接下载&#xff0c;解压缩 start nginx就可以使了&#xff0c;常用命令&#xff1a; start nginx # 启动 nginx -s reload # 修改配置后重新加载生效 nginx -s reopen # 重新打开日志文件 nginx -t # 配置文件检测是否正确 1.2 安装Jenkins…

ASP.NET Core Web 应用程序系列(二)- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)...

在上一章中主要和大家分享在MVC当中如何使用ASP.NET Core内置的DI进行批量依赖注入&#xff0c;本章将继续和大家分享在ASP.NET Core中如何使用Autofac替换自带DI进行批量依赖注入。 PS&#xff1a;本章将主要采用构造函数注入的方式&#xff0c;下一章将继续分享如何使之能够同…

Java过滤器与SpringMVC拦截器之间的关系与区别

今天学习和认识了一下&#xff0c;过滤器和SpringMVC的拦截器的区别&#xff0c;学到了不少的东西&#xff0c;以前一直以为拦截器就是过滤器实现的&#xff0c;现在想想还真是一种错误啊&#xff0c;而且看的比较粗浅&#xff0c;没有一个全局而又细致的认识&#xff0c;由于已…

二次幂权限设计

设置含有的权限如增删改查减为1,2,4,8,16 如果A包含增删改这5个权限&#xff0c;那A的值为1247 如果B包含增改查这5个权限&#xff0c;那A的值为14813 如果C包含增删改查减这5个权限&#xff0c;那A的值为12481631 7二进制为111,13的二进制为1101,31二进制为11111 1二进制为1&a…

使用putty在linux主机和windows主机之间拷贝文件(已测试可执行)

转载于&#xff0c;请点击 首先下载putty&#xff0c;putty下载地址zip&#xff0c; 解压zip发现里面有plink.exe pscp.exe psftp.exe putty.exe puttygen.exe puttytel.exe等可执行文件&#xff0c;如果只是想要链接主机做一些操作那么使用putty.exe&#xff0c;要想要上传 …

ASP.NET Core Web 应用程序系列(三)- 在ASP.NET Core中使用Autofac替换自带DI进行构造函数和属性的批量依赖注入(MVC当中应用)...

在上一章中主要和大家分享了在ASP.NET Core中如何使用Autofac替换自带DI进行构造函数的批量依赖注入&#xff0c;本章将和大家继续分享如何使之能够同时支持属性的批量依赖注入。 约定&#xff1a; 1、仓储层接口都以“I”开头&#xff0c;以“Repository”结尾。仓储层实现都以…

可视化caffe模型结构及在线可视化

在线可视化caffe模型结构 http://ethereon.github.io/netscope/#/editor 假设Caffe的目录是$(CAFFE_ROOT) 1.编译caffe的python接口 $ make pycaffe 2.装各种依赖 $ pip install pydot $ sudo apt-get install graphviz 3.可视化模型 draw_net.py执行的时候带三个参数 …

iOS核心动画之CALayer(1)

本文目录 一、什么是CALayer二、CALayer的简单使用 回到顶部一、什么是CALayer * 在iOS系统中&#xff0c;你能看得见摸得着的东西基本上都是UIView&#xff0c;比如一个按钮、一个文本标签、一个文本输入框、一个图标等等&#xff0c;这些都是UIView。 * 其实UIView之所以能显…

ASP.NET Core Web 应用程序系列(四)- ASP.NET Core 异步编程之async await

PS&#xff1a;异步编程的本质就是新开任务线程来处理。 约定&#xff1a;异步的方法名均以Async结尾。 实际上呢&#xff0c;异步编程就是通过Task.Run()来实现的。 了解线程的人都知道&#xff0c;新开一个线程来处理事务这个很常见&#xff0c;但是在以往是没办法接收线程里…

iOS核心动画之CALayer-layer的创建

本文目录 一、添加一个简单的图层二、添加一个显示图片的图层三、为什么CALayer中使用CGColorRef和CGImageRef这2种数据类型&#xff0c;而不用UIColor和UIImage&#xff1f;四、UIView和CALayer的选择五、UIView和CALayer的其他关系 * 上一讲已经说过&#xff0c;UIView内部默…

iOS核心动画之CALayer-隐式动画

本文目录 一、隐式动画属性二、position和anchorPoint 回到顶部一、隐式动画属性 * 在前面几讲中已经提到&#xff0c;每一个UIView内部都默认关联着一个CALayer&#xff0c;我们可用称这个Layer为Root Layer&#xff08;根层&#xff09;。所有的非Root Layer&#xff0c;也就…

iOS核心动画之CALayer-自定义层

本文目录 一、自定义层的方法1二、自定义层的方法2 三、其他 自定义层&#xff0c;其实就是在层上绘图&#xff0c;一共有2种方法&#xff0c;下面详细介绍一下。 回到顶部一、自定义层的方法1 方法描述&#xff1a;创建一个CALayer的子类&#xff0c;然后覆盖drawInContext:方…

iOS核心动画之CoreAnimation

本文目录一、Core Animation简介二、Core Animation的使用步骤三、CAAnimation四、CAPropertyAnimation 回到顶部一、Core Animation简介 * Core Animation&#xff0c;中文翻译为核心动画&#xff0c;它是一组非常强大的动画处理API&#xff0c;使用它能做出非常炫丽的动画效果…

iOS核心动画 Core Animation2-CABasicAnimation

Core Animation2-CABasicAnimation 本文目录 一、平移动画二、缩放动画三、旋转动画四、其他 CABasicAnimation是CAPropertyAnimation的子类&#xff0c;使用它可以实现一些基本的动画效果&#xff0c;它可以让CALayer的某个属性从某个值渐变到另一个值。下面就用CABasicAnimat…