初始socket模块和巧解粘包问题

1.什么是socket?

  两个进程如果需要进行通讯最基本的一个前提能够唯一的标示一个进程,在本地进程通讯中我们可以使用PID来唯一标示一个进程,但PID只在本地唯一,网络中的两个进程PID冲突几率很大,这时候我们需要另辟它径了,我们知道IP层的ip地址可以唯一标示主机,而TCP层协议和端口号可以唯一标示主机的一个进程,这样我们可以利用ip地址+协议+端口号唯一标示网络中的一个进程。

  能够唯一标示网络中的进程后,它们就可以利用socket进行通信了,什么是socket呢?我们经常把socket翻译为套接字,socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。

  socket是应用层与TCP/IP协议族通信的中间软件层,它是一组接口。在设计模式中,socket其实就是一个门面模式,它把复杂的TCP/IP协议隐藏在socket接口后面,对用户来说,一组简单的接口就是全部,让socket去组织数据,以符合之id那个的协议。

  所以,我们无需深入理解TCP/UDP协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,那么写出的程序自然是符合TCP/UDP标准的。

2.套接字的种类

  我们认识的套接字分为两种:1)基于文件的套接字:AF_UNIX

                2) 基于协议的套接字:AF_INET

  unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一台机器上可以通过访问同一个文件系统间接完成通信。但是,AF_INET是使用最为广泛的一个,python支持多种地址家族,但是我们只关心网络编程,所以大部分我们只是用AF_INET。

3.套接字的使用

1)基本使用

import socket# 买手机 默认得到是一个TCP的socket
server = socket.socket()server.bind(("127.0.0.1",16888))  # 绑定手机卡

server.listen() # 开始待机# 得到对方的socket对象与地址
client,addr = server.accept() # 接收通话请求 # 该函数会阻塞 直到有连接请求过来# buffersize 表示应用程序的缓冲区大小     recv其实是 从系统缓冲区读取数据到应用程序
data = client.recv(1024)   # 该函数会阻塞 直到操作缓冲区有数据位置print("收到客户端发来的数据:%s" % data.decode("utf-8"))# 发生的数据必须为bytes类型
client.send(data)
client.close() #挂断电话
server.close() # 关机
服务器
import socketclient = socket.socket()client.connect(("127.0.0.1",16888))client.send("hello 服务器".encode("utf-8"))data = client.recv(1024)   # 该函数会阻塞 直到操作缓冲区有数据位置print("收到服务器:%s" % data.decode("utf-8"))client.close()
客户端

2)通信循环

import socket
server=socket.socket()
server.bind(("127.0.0.1",16888))
# 开始待机
server.listen()# 通信循环
while True:client,addr=server.accept()while True:try:# 如果是windows 对方强行关闭连接会抛出异常# 如果是linux 不会抛出异常 会收到空的数据包进入死循环data=client.recv(1024)if not data :client.close()breakprint('收到数据%s:'%data.decode('utf-8'))client.send(data)except ConnectionResetError:print('客户端关闭连接')client.close()break
# 挂断电话
client.close()
# 关机
server.close()
服务端
import socket
client=socket.socket()
client.connect(("127.0.0.1",16888))
while True:msg=input('>>>:')client.send(msg.encode('utf-8'))data=client.recv(1024)print('收到服务器:%s'%data.decode('utf-8'))
client.close()
客户端

3)TCP协议的异常处理

import  socketserver = socket.socket()server.bind(("127.0.0.1",8888))server.listen()client,addr = server.accept()while True:try:data = client.recv(1024)if not data:print("对方已经关闭.....")breakprint(data.decode("utf-8"))client.send(data.upper())except ConnectionResetError:print("对方异常关闭连接...")client.close()
server.close()
服务端
import  socketclient = socket.socket()
client.connect(("127.0.0.1",8888))client.send("hello".encode("utf-8"))data = client.recv(1024)
print(data.decode("utf-8"))client.close()
客户端

4.粘包问题(处理方式)

   粘包产生的原因:1.对于数据接受端来说,它不知道自己接受的将会是多大的数据。

          2.对于发送方来说,TCP内部会将很小的数据都打包在一起,一起发送。

粘包的解决方案:(以操作shell指令为例)

 

import socket, subprocess
import json
import structIP_PORT = ('127.0.0.1', 8888)
server = socket.socket()
server.bind(IP_PORT)
server.listen(5)while True:conn, addr = server.accept()while True:try:data = conn.recv(1024).decode('utf-8')if len(data) == 0: breakobj = subprocess.Popen(data, shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)stdout = obj.stdout.read()stderr = obj.stderr.read()info_dic = {'name': '二进制指令','len': len(stdout + stderr)}info_bytes = json.dumps(info_dic).encode('utf-8')header = struct.pack('i', len(info_bytes))conn.send(header)conn.send(info_bytes)conn.send(stderr + stdout)except ConnectionResetError:breakconn.close()
服务端

 

import socket
import struct
import jsonIP_PORT = ('127.0.0.1', 8888)
cilent = socket.socket()
cilent.connect(IP_PORT)while True:cmd = input('cmd>>>>')if len(cmd) == 0: continuecilent.send(cmd.encode('utf-8'))header = cilent.recv(4)header_len = struct.unpack('i', header)[0]info_dic = json.loads(cilent.recv(header_len).decode('utf-8'))total_size = info_dic.get('len')rec_size = 0res = b''while rec_size < total_size:data = cilent.recv(1024)res += datarec_size += len(data)print(res.decode('gbk'))
客户端

5.案列:客户端传送大文件

 

import socket
import json
import structIP_PORT = ('127.0.0.1', 9633)
server = socket.socket()
server.bind(IP_PORT)
server.listen(5)while True:conn, addr = server.accept()while True:try:# 接收报头header = conn.recv(4)# 解包得到字典的真实长度file_bytes = struct.unpack('i',header)[0]# 反序列化成字典file_info = json.loads(conn.recv(file_bytes).decode('utf-8'))file_name = file_info.get('file_name')file_size = file_info.get('file_size')rec_size = 0# 开始接受文件,并写入with open(file_name, 'wb') as w:while rec_size < file_size:data = conn.recv(1024)w.write(data)rec_size += len(data)print(file_info.get('msg'))except ConnectionResetError:breakconn.close()
server

 

import socket
import json
import struct
import osIP_PORT = ('127.0.0.1', 9633)
cilent = socket.socket()
cilent.connect(IP_PORT)# 文件的大小
file_size = os.path.getsize(r'E:\fullstack_s4\day32\3.标记删除.mp4')
# 文件的名字
file_name = "王鹏是小猪.mp4"
# 定义文件信息字典
file_info = {'file_name': file_name,'file_size ': file_size,'msg': "不要老师看?会被影响的!"
}
# 将字典序列化为二进制
header_bytes = json.dumps(file_info).encode('utf-8')
# 打包并生报头
header = struct.pack('i', len(header_bytes))
# 发送报头
cilent.send(header)
# 发送报头字典
cilent.send(header_bytes)
# 发送真实的数据
with open(r'E:\fullstack_s4\day32\3.标记删除.mp4', 'rb') as f:for line in f:cilent.send(line)
cilent

6.UDP协议

  UDP协议属于数据报协议,没有双向通道的存在。

  相比TCP协议: 1.他不会存在粘包问题

          2.客户端可以发空

         3.看似是并发过程

         4.在不启动服务短的情况下,运行客户端不会报错

 

import socketIP_PORT = ('127.0.0.1', 8080)
server = socket.socket(socket.SOCK_DGRAM)
server.bind(IP_PORT)while True:conn, addr = server.recvfrom(1024)print(conn, addr)server.sendto(conn.upper(), addr)
UDPserver

 

import socketIP_PORT = ('127.0.0.1', 8080)
cilent = socket.socket(socket.SOCK_DGRAM)cilent.sendto(b'hello baby',IP_PORT)
UDPcilent

 

7.socketserver模块

 

import socketserverclass MyServer(socketserver.BaseRequestHandler):def handle(self):while True:data = self.request.recv(1024)print(data)self.request.send(data.upper())if __name__ == '__main__':server = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyServer)server.serve_forever()
服务端

 

import socketcilent = socket.socket()
cilent.connect(('127.0.0.1',8080))while True:cilent.send(b'hello')data = cilent.recv(1024)print(data)
客户端

 

转载于:https://www.cnblogs.com/wanglei957/p/10806350.html

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

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

相关文章

webpack常用loader和plugin及打包速度优化

优化 或 也可以用&#xff1a; 备用&#xff1a; 慎用的配置&#xff0c;用的不好会增加打包时间&#xff1a; 代码丑化插件&#xff1a; 更多专业前端知识&#xff0c;请上 【猿2048】www.mk2048.com

react-native 热更新react-native-pushy集成遇到的问题

主要步骤按官方文档实现&#xff0c;这里只记录遇到的一些小坑 官方文档 run-android时NDK报错 前提是NDK已安装并且环境变量已设置 根据报错提示在 android/local.properties文件里加入ndk.dir~/Library/Android/android-ndk-r10e //这里改成你自己的ndk路径 cxxbridge找…

Keil5 仿真测试出现Cannot Load Flash Device Description 解决方法

1.用ST的烧录软件检测&#xff0c;可以烧录对应的Hex文件。 2.点击魔术棒&#xff0c;Debug选项卡检测芯片型号是否和当前芯片对应 3.在Flash Download选项卡中检查发现没有对应的芯片型号 4.点击Add 选项&#xff0c;选择对应的Flash类型如图&#xff1a; 添加Flash类型后&…

Hadoop—MapReducer统计文件的单词出现的个数

1. MapReduce 统计文件的单词出现的个数 Mapper: 处理具体文本&#xff0c;发送结果 Reducer: 合并各个Mapper发送过来的结果 Job: 制定相关配置&#xff0c;框架 Mapper package cn.itcast.hadoop.mr.wordcount;import java.io.IOException;import org.apache.hadoop.io.LongW…

课堂作业2

1、动手动脑 阅读示例: EnumTest.java&#xff0c;运行它&#xff0c;分析运行结果&#xff1f;你能得到什么结论&#xff1f;你掌握了枚举类型的基本用法了吗&#xff1f; public class EnumTest {public static void main(String[] args) {Size sSize.SMALL;Size tSize.LARGE…

(转)详解Vs2008下打包安装程序的一些技巧(含win7下提权限、卸载以及安装时定向到网页)...

1、怎么使得程序窗口左上角和任务栏有图标&#xff0c;如下图所示&#xff1a; 其实这个问题不应该放到程序打包这部分讲&#xff0c;只不过对于一些初学者而言&#xff0c;在这提下也许会有很大的帮助&#xff08;想到自己刚学.net那会了&#xff0c;呵呵&#xff09;。方法之…

项目实战报异常Exception及决绝方案

1、报LifecycleException&#xff0c;再配置一下jdk即可&#xff0c;然后再手动添加maven 解决方法&#xff1a; 然后,手动添加jar包 2、maven 项目,右键maven build启动项目的时候&#xff0c;报下面错误&#xff0c;没有在pom配置tomcat7插件 3、报找不到beans插件:更新一下项…

世界主要遥感卫星

世界主要遥感卫星QuickbirdSpot-4Spot-4法国“太阳神”1A神舟飞船神舟飞船“哈勃”望远镜RADASAT神舟飞船国际空间站国际空间站 SPOT2Shutsacn IKONOS CBERS-1JersSpot-4 “哈勃”望远镜 CBERS-1 Landsat 5美国“KH-11”侦察卫星 Spot-5 ERS Landsat 7OrbView-3 美国间谍卫星…

VMware配置linux网络步骤

1.我们要用桥接网络模式 2.设置桥接网络&#xff0c;VMnet1或者VMnet0就是桥接网络&#xff0c;我们用的就是桥接 VMnet8是NAT 在上面的图配置好ip和dns&#xff0c;要与windowss是同一个网段&#xff0c;网关一般不设置 3.设置linux网络里面设置这4项&#xff0c;记住dns可以不…

使用IntelliJ书签

这是有关IntelliJ的精美书签功能的快速帖子。 IntelliJ使您可以为单行代码添加书签。 将某行添加为书签后&#xff0c;您可以使用多种方法直接跳回到该行。 因此&#xff0c;最好在您经常使用的代码位置添加书签。 要创建一个新书签&#xff0c;只需在代码编辑器中按F11键。 …

ECMA-335 (CLI) 标准 读书笔记——总结CLI类型系统(上)

看到类型系统的概述时&#xff0c;就忍不住按图索骥&#xff0c;想搞清楚CLI如何定义的整个类型系统。于是翻遍了整个标准&#xff0c;将类型系统中最核心的、与运行平台密切相关的类型定义与说明整理了出来&#xff0c;以供理清思路。 标准的第四部指出&#xff0c;CLI的核心是…

centos7安装openjdk8

首先&#xff0c;打开openjdk安装官网 http://openjdk.java.net/install/ 输入安装命令&#xff1a; su -c "yum install java-1.8.0-openjdk" 装完之后会有提示版本跟安装的路径&#xff1b;在/usr/lib/jvm下可以查看到对应的名字&#xff0c;ls-l 配置环境变量&…

CSB文件上传漏洞 -->Day4(图片挂马)

22二号&#xff0c;冬至啦&#xff0c;深圳这边只有5&#xff08;尊嘟好冷啊&#xff09;&#xff0c;写这篇文章的时候都已经是凌晨一点了&#xff0c;相信大部分的人都在温暖的被窝里面了吧&#xff01;&#xff01;&#xff08;可怜的我&#xff0c;还得写writeup&#xff0…

微信小程序禁止刷新之后苹果端还可以下拉的问题

一、问题描述 最近在做一个小程序项目&#xff0c;需要禁止下拉刷新&#xff0c;于是在page.json里面添加了这段话 "enablePullDownRefresh":false 全局关闭下拉刷新&#xff0c;这段话确实禁止了下拉刷新&#xff0c;无论是安卓手机端还是苹果端&#xff0c;但是在…

调试OpenJDK

knowyourmeme.com/photos/531557 THX为mihn 有时调试Java代码还不够&#xff0c;我们需要逐步了解Java的本机部分。 我花了一些时间来实现JDK的正确状态&#xff0c;所以简短的描述可能对开始旅行的人很有用。 我将使用全新的OpenJDK 9&#xff01; 首先&#xff0c;您必须通过…

算法题解:旋转数组的最小数字

题目描述 把一个数组最开始的若干个元素搬到数组的末尾&#xff0c;我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转&#xff0c;输出旋转数组的最小元素。 解题思路 将旋转数组对半分可以得到一个包含最小元素的新旋转数组&#xff0c;以及一个非递减排序的数组。新…

函数的自执行,变量提升和函数提升

其实之前虽然刚开始学习JavaScript的时候经常看到function add(){}、var addfunction(){}、function(){}之类的这种写法&#xff0c;但是具体是什么叫什么却没有去考虑过这个问题…… function add(){}这种写法叫做函数声明 var addfunction(){}这种写法叫做函数表达式 fun…

Python之机器学习-sklearn生成随机数据

sklearn-生成随机数据 import numpy as np import pandas as pd import matplotlib.pyplot as plt from matplotlib.font_manager import FontProperties from sklearn import datasets %matplotlib inline font FontProperties(fname/Library/Fonts/Heiti.ttc) 多标签分类数据…

外汇游乐场

介绍 F X Playground是基于JavaFX的原型制作工具或实时编辑器&#xff0c;它消除了编译Java代码的步骤。 这个概念并不是什么新鲜事物&#xff0c;例如在网络世界中&#xff0c;有许多HTML5 游乐场提供在线编辑器&#xff0c;使开发人员可以快速原型化或尝试各种JavaScript库。…

轻轻松松看懂Spring AOP源码

轻轻松松看懂Spring AOP源码 https://baijiahao.baidu.com/s?id1596466083334197175&wfrspider&forpc 如果对spring的核心容器和JDK动态代理、CGLIB有所了解&#xff0c;接下来再看spring AOP源码会比较容易。文中所有代码片段截图对应的spring版本是5.0。 本文内容曾…