当前位置: 首页 > news >正文

Python网络编程之Socket(套接字)

文章目录

  • 一、Socket概念
  • 二、套接字的发展史及分类
  • 三、Socket的使用
      • 语法格式(基于TCP协议)
      • 1.基于TCP协议的套接字(socket)编程
        • 半连接池
      • 2.基于UDP协议的套接字(socket)编程
        • 也可以使用服务端只接收客户端消息
  • 黏包现象

一、Socket概念

Socket套接字,一种独立于协议的网络编程接口,就是对网络中不同主机上的应用进程之间进行双向通信的端点。
TCP把连接作为最基本的对象,每一条TCP连接都有两个端点,这种端点我们叫做套接字(Socket)。

IP层的IP地址可以唯一标示主机,而TCP层协议和端口号可以唯一标示主机的一个进程,这样我们可以利用IP地址+协议+端口号唯一标示网络中的一个进程。能够唯一标示网络中的进程后,它们就可以利用socket进行通信了

python中,我们利用Socket套接字来实现网络通信,可以说套接字是实现网络编程进行数据传输的一种技术手段。
Socket用于描述IP地址和端口,应用程序通常通过’套接字’相网络发出请求或者应答网络请求。
Socket主要是基于应用层和传输层之间,是一个中间的抽象层,功能是将复杂的TCP/IP协议族隐藏在Socket接口后面。
应用程序通过套接字发送或接收数据,socket模块针对服务器端和客户端Socket进行像对文件一样的打开、读写和关闭等操作。
套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。网络套接字是IP地址与端口的组合。

在这里插入图片描述

二、套接字的发展史及分类

套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。 因此,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字”。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。这也被称进程间通讯,或 IPC。套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的。

  • 基于文件类型的套接字家族:
    套接字家族的名字:AF_UNIX

    unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信

  • 基于网络类型的套接字家族:
    套接字家族的名字:AF_INET

    (还有AF_INET6被用于ipv6,还有一些其他的地址家族,不过,他们要么是只用于某个平台,要么就是已经被废弃,或者是很少被使用,或者是根本没有实现,所有地址家族中,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET)

三、Socket的使用

通过指定地址簇和socket类型来进行创建。

地址簇描述
Socket.AF_UNIX只能够用于单一的Unix系统进程间通信
Socket.AF_INET服务器之间网络通信IPv4
Socket.AF_INET6IPv6
Socket类型描述
Socket.SOCK_STREAM流式socket,for TCP
Socket.SOCK_DGRAM数据报式socket,for UDP
Socket.SOCK_RAW原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。

服务器与客户端交互过程:
在这里插入图片描述

语法格式(基于TCP协议)

									'''服务端'''import socket
'''基于TCP协议的套接字(Socket)编程'''
'''以后养成一个查看源码编写代码的思路!!!!''''''服务端比客户端先运行,服务端先运行然后等待客户端连接'''# 1.产生一个socket对象并指定采用的通信版本和协议(括号内不写默认就是TCP协议)
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
'''
AF_INET, type=SOCK_STREAM   AF_INET, type=SOCK_DGRAM
基于TCP协议                  基于UDP协议
'''# 2.绑定IP地址(ip)和端口号(port)(需要用元组的形式)
'''def bind(self, __address: _Address | bytes) -> None: ...'''
# 绑定的IP地址可以省略,代表绑定本机,第一个参数为ip地址,第二个参数为端口号
server.bind(('127.0.0.1', 8000))
'''127.0.0.1为本地回环地址,只有自己电脑可以访问'''# 3.服务器做监听,也称为半连接池(需要用int类型,服务器能够同时等待客户端的数量)(排队数量不包含正在执行的)
'''    def listen(self, __backlog: int = ...) -> None: ...'''
# listen有一个参数,是一个数值,参数越大,以后可以连接的客户端越多,参数越小链接的客户端越小
server.listen(3)
print('form Listen')# 4.等待接收客户端的连接请求
'三次握手'
sock, addr = server.accept()  # return sock,addr
# 运行到这里会等待客户端发送信息才继续下面的运行
'''sock就是双向通道,addr就是客户端地址'''
print('等待完成!')# 5.接收客户端发送过来的消息,(接收到的类型是bytes类型,二进制的)
'''def recv(self, __bufsize: int, __flags: int = ...) -> bytes: ...'''
data = sock.recv(1024)  # 括号内代表的是一次接收最多1024个字节
'''recv()接收     send()发送'''
print('接收到了客户端的数据:',data)# 6.给客户端发送消息,注意消息必须是bytes类型的
sock.send(data.upper())  # 我这里就只是给客户端发送的消息转成大写# 7.关闭双向通道
'四次挥手'
sock.close()# 8.关闭服务器
server.close()print('==============================')'''客户端'''
import socket
'''运行程序时一定要确保先运行了服务器,之后才是客户端'''
# 1.生成socket对象指定类型和协议
client1 = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)# 2.通过IP地址和端口号连接服务端
'''def connect(self, __address: _Address | bytes) -> None: ...'''
client1.connect(('127.0.0.1', 8000))# 3.直接给服务端发送消息
client1.send('hello world'.encode('utf-8'))# 4.接收服务端发送过来的消息
data = client1.recv(1024)
print('收到服务端发来的消息:', data.decode('utf-8'))# 5.断开与服务端的链接
client1.close()

1.基于TCP协议的套接字(socket)编程

TCP(Transmission Control Protocol)可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。使用TCP的应用:Web浏览器;电子邮件、文件传输程序。

服务端:

	import socket# 生成一个socket对象,设定类型和协议
server1 = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)# 为socket设置IP地址,端口号
server1.bind(('127.0.0.1', 8080))# 给服务器添加同时监听几个客户端,
server1.listen(3)while True:# 等待客户端发来消息sock, addr = server1.accept()# sock双向通道,addr客户端地址while True:try:# 避免用户断开后,直接报错,自动捕获异常# 接收客户端发来的消息 二进制data = sock.recv(2048)print('接收到了客户端发来的消息:', data.decode('utf-8'))# 给客户端回复消息mag = input('请输入回复的消息>>>:').strip()sock.send(mag.encode('utf-8'))except Exception as f:print(f)break# 关闭双向通道
sock.close()# 断开服务器链接
server1.close()

客户端:

	import socket# 生成一个socket对象,设置类型和协议
client4 = socket.socket(family = socket.AF_INET,type=socket.SOCK_STREAM)# 连接到服务器
client4.connect(('127.0.0.1',8080))while True:# 向服务器发送消息mag = input('请输入发送的消息>>>:').strip()if len(mag) == 0:print('请输入有效信息!')continueif mag == 'yes':print('已断开与服务器连接!')breakclient4.send(mag.encode('utf-8'))  # 转码# 接收服务器回应的消息 字节data = client4.recv(2048)print('接收到了服务器发来的消息:',data.decode('utf-8'))  # 解码print('是否不在回复,断开连接?,请输入yes即可!')# 断开连接
client4.close()

有时候我们在重启服务端时,会出现端口被占用的情况。这是因为虽然连接已经关闭,但是端口还没来得及释放。
在这里插入图片描述
两种解决方案:
* 更换端口。
* bind绑定IP之前添加一个参数,来达到端口复用的目的。

import osserver = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)# 绑定ip地址和端口,127.0.0.1代表回环地址,只能当前计算机访问
server.bind(('127.0.0.1',8080))
半连接池
	半连接池server.listen(5)意思就是同时可以运行五个客户端 如果多于五个则会报错需要等待前面五个客户端其中一个结束 则会有多余的位置给到第六个

2.基于UDP协议的套接字(socket)编程

UDP(User Datagram Protocol)不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。

udp是无连接的,所以发送数据前不需要先建立连接。
我们可以使用多个客户端与服务端进行数据发送,服务端可以逐个回复
udp发送数据采用的是数据报模式,数据会一次性全部发过去,如果未接收到也不会保存,安全性没有保障,但传输速率较快。

服务端:

	import socket
'''基于UDP协议的套接字(socket)编程'''# 生成一个socket对象 设置类型和协议
server = socket.socket(family = socket.AF_INET,type = socket.SOCK_DGRAM)
'''这里因为要设置成UDP协议,所以type = socket.SOCK_DGRAM'''# 设置服务器IP地址及端口号
server.bind(('127.0.0.1',8848))while True:# 接受客户端发送来的信息,以及发送者的ip以及端口(UDP不需要建立连接)data,addr = server.recvfrom(2048)print(f"收到客户端{addr}发来的消息:",data.decode('utf-8'))# 向发送者回复信息mag = input('请输入回复的消息>>>>:').strip()server.sendto(mag.encode('utf-8'), addr)

客户端:

	import socket# 生成一个socket对象 设置类型和协议
client = socket.socket(family = socket.AF_INET,type = socket.SOCK_DGRAM)server_ip = ('127.0.0.1',8848)  # 写好的ip地址和端口
# 无需和服务端建立连接while True:mag = input('请输入发送的消息>>>:').strip()# 无需判断是否为空,因为UDP每次发送都不只是单纯的数据,还有ip和端口信息# 直接向写好的ip和端口发送数据client.sendto(mag.encode('utf-8'),server_ip)# 接收它的返回值data,addr = client.recvfrom(2048)print(f"接收到了{addr}的消息:",data.decode('utf-8'))
也可以使用服务端只接收客户端消息

服务端:

	import socket
server = socket.socket(family = socket.AF_INET,type = socket.SOCK_DGRAM)server.bind(('127.0.0.1',8888))# 无需建立连接while True:data,addr = server.recvfrom(2048)print(f"接收到了发送者{addr}发来的消息:",data.decode('utf-8'))

客户端:

	import socketclient = socket.socket(family = socket.AF_INET,type = socket.SOCK_DGRAM)# 无需建立连接while True:# 直接给对应的ip地址和端口号发送信息mag = input('请输入发送的消息>>>:').strip()client.sendto(mag.encode('utf-8'),('127.0.0.1',8888))

黏包现象

	1.服务端连续执行三次recv2.客户端连续执行三次send问题:服务端一次性接收到了客户端三次的消息 该现象称为"黏包现象"黏包现象产生的原因1.不知道每次的数据到底多大2.TCP也称为流式协议:数据像水流一样绵绵不绝没有间隔(TCP会针对数据量较小且发送间隔较短的多条数据一次性合并打包发送)避免黏包现象的核心思路\关键点如何明确即将接收的数据具体有多大ps:如何将长度变化的数据全部制作成固定长度的数据

相关文章:

Python网络编程之Socket(套接字)

文章目录 一、Socket概念二、套接字的发展史及分类三、Socket的使用语法格式(基于TCP协议)1.基于TCP协议的套接字(socket)编程半连接池 2.基于UDP协议的套接字(socket)编程也可以使用服务端只接收客户端消息 黏包现象 一、Socket概念 Socket套接字,一种独立于协议的…...

金山终端安全系统V9.0 SQL注入漏洞复现

0x01 产品简介 金山终端安全系统是一款为企业提供终端防护的安全产品,针对恶意软件、病毒和外部攻击提供防范措施,帮助维护企业数据和网络。 0x02 漏洞概述 金山终端安全系统V9.0 /inter/update_software_info_v2.php页面存在sql注入漏洞,该…...

Radius OTP完成堡垒机登录认证 安当加密

Radius OTP(One-Time Password)是一种用于身份验证的协议,它通过向用户发送一个一次性密码来验证用户的身份。使用Radius OTP可以实现堡垒机登录,以下是一些实现步骤: 1、安装Radius服务器 首先需要安装Radius服务器…...

ROS opencv 人脸识别

人脸识别需要在输入的图像中确定人脸(如果存在)的位置、大小和姿态,往往用于生物特征识别、视频监听、人机交互等应用中。2001年,Viola和Jones提出了基于Haar特征的级联分类器对象检测算法,并在2002年由Lienhart和Mayd…...

文心一言 4.0 ERNIE-Bot 4.0 :ERNIE-Bot 4.0 大模型深度测试体验报告

本心、输入输出、结果 文章目录 文心一言 4.0 ERNIE-Bot 4.0 :ERNIE-Bot 4.0 大模型深度测试体验报告前言相关跳转文心一言 4.0 ERNIE-Bot 4.0 接口简介Bash 请求示例代码Windows 模式使用 Python 请求如果直接使用官方提供的代码文心一言 4.0 ERNIE-Bot 4.0 API 在…...

华为OD机考B卷 | 100分】阿里巴巴找黄金宝箱(JAVA题解——也许是全网最详)

前言 本人是算法小白,甚至也没有做过Leetcode。所以,我相信【同为菜鸡的我更能理解作为菜鸡的你们的痛点】。 题干 1. 题目描述 一贫如洗的樵夫阿里巴巴在去砍柴的路上,无意中发现了强盗集团的藏宝地,藏宝地有编号从0~N的箱子&…...

请求转发和重定向区别

两者区别: 1.转发在一次请求中完成,重定向是两次请求 2.转发操作发生在服务器内部,重定向是在浏览器执行操作 3.转发地址栏不变,重定向地址栏变化(两次请求,两个地址) 4.转发可以在一次请求中共…...

JS如何判断对象为空?以及各自的缺点。

JS如何判断对象为空?以及各自的缺点。 Object.keys() 通过 Object.keys() 来获取对象的键进行判断。 function isEmpty(obj) {return Object.keys(obj).length 0; }console.log(isEmpty({})); // true console.log(isEmpty({ a: 1 })); // false缺点&#xff1a…...

同城代驾开源版小程序开发

同城代驾开源版小程序开发 功能特性描述: 定价模式:本系统支持灵活的计价模式,包括白天和夜晚的起步价、起步里程、每公里价以及超时费用,从而满足不同时段的定价需求。 实时路径计算:通过集成腾讯地图的软件开发工…...

【Python机器学习】零基础掌握ShrunkCovariance协方差估计

有没有想过如何准确地评估股票投资的风险? 在投资领域,了解各种资产(如股票、债券等)之间的相关性和波动性是非常重要的。常用的方法是计算资产收益率的协方差矩阵,但这个矩阵在样本量少或数据质量不高的情况下可能会产生误导。那么,有没有更好的方法来解决这个问题呢?…...

精神科常用评估量表汇总,建议收藏!

根据精神科医生的量表使用情况,笔者整理了10个精神科常用量表,可在线评测直接出结果,可转发使用,可生成二维码使用,可创建项目进行数据管理,有需要的小伙伴赶紧收藏! 抑郁自评量表 抑郁自评量表…...

Python之切片

Python之切片 切片 通过给定的索引区间获得线性结构的一部分数据start、stop、step为整数,可以是正整数、负整数、零start为0时,可以省略stop为末尾时,可以省略step为1时,可以省略切片时,索引超过上界(右边界)&#…...

OpenCV显示中文(python)

OpenCV添加文字的方法putText(…),添加英文是没有问题的,但如果你要添加中文就会出现“???”的乱码,需要特殊处理一下。 下文提供封装好的(代码)方法,供OpenCV添加中文使…...

k8s-18 认证授权

Authentication (认证) 认证方式现共有8种,可以启用一种或多种认证方式,只要有一种认证方式通过,就不再进行其它方式的认证。通常启用X509 Client Certs和Service Accout Tokens两种认证方式 Kubernetes集群有两类用户:由Kubernetes管理的Ser…...

WebAPI+EF连接SQL Server数据库

右击解决方案-添加-新建项目-选择“类库(.NET Framework)”,新建的项目取名叫WebApi1.EF 添加EF: 新建一个ADO实体数据模型 选择DBFirst 数据源选择MySql 填写数据库地址及账号密码 选择实体框架版本 选择在数据库中的表User 到此配置完成&am…...

maven-plugin-shade 详解1

maven-plugin-shade 是 Maven 的一个插件,它的作用是将多个 jar 包合并成一个 jar,同时将其中的依赖关系也合并到该 jar 中。这个插件常用于创建可执行 jar 包和打包 web 应用程序。 下面是 maven-plugin-shade 的一些常用配置: 打包的形式&…...

C#中LinkedList、Queue<T>和Stack<T>的使用

1、LinkedList(链表) 链表中元素存储内存中是不连续分配,每个元素都有记录前后节点,节点值可以重复,不能通过下标访问,泛型的使用保证类型安全,可以避免装箱拆箱,找元素就只能遍历,查找不方便&…...

流程图如何制作?好用的11款流程图软件盘点!

流程图是一种强大的可视化工具,用于清晰地展示各种过程和步骤,应用非常广泛,在各个行业中随处可见,凡是涉及流程步骤的场景,都可以用到流程图,那么问题来了:流程图如何制作? 这篇文…...

windows本地文件上传linux 或 linux输入rz命令后出现receive.**B0100000023be50

这种现象需要客户端支持,或者使用Xshell工具等 但是有一种简单的方法,使用 sftp rootip地址 // 比如 sftp root127.0.0.2 当然,你要记得登录远程节点的密码:...

C# CodeFormer Inpainting 人脸填充

效果 项目 代码 using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms;namespace CodeFormer_D…...

将Sketch文件转化为PSD文件的简单在线工具!

设计工作不仅需要UI设计工具,还需要Photoshop。常见的UI设计工具Sketch与Photoshop软件不兼容。如果你想在实际工作中完成Sketch转psd,你需要使用其他软件进行转换。但是在转换过程中容易丢失文件,导致同样的工作需要重复多次才能完成&#x…...

【广州华锐互动】利用AR进行野外地质调查学习,培养学生实践能力

在科技发展的驱动下,AR(增强现实)技术已经在许多领域中找到了应用,包括医疗、教育、建筑和娱乐等。然而,有一个领域尚未充分利用AR技术的潜力,那就是野外地质调查。通过将AR技术引入到这个传统上需要大量人…...

Jmeter快速入门

引言 对于初学者来说,可能会觉得jmeter有些难入手。不过,别担心!在我开始使用Jmeter之前,也曾面临着同样的问题。 但是,通过一番尝试和学习,我现在可以自如地运用Jmeter进行性能测试了。 接下来&#xf…...

详解js数组操作——filter()方法

引言 在JavaScript中,我们经常需要对数组进行筛选,以便根据特定的条件获取所需的元素。而JavaScript的filter()方法就是一个非常有用的工具,它可以帮助我们轻松地筛选数组中的元素。本文将介绍如何使用filter()方法,以及一些实用…...

基于MATLAB的图像条形码识别系统(matlab毕毕业设计2)

摘要 : 本论文旨在介绍一种基于MATLAB的图像条形码识别系统。该系统利用计算机视觉技术和图像处理算法,实现对不同类型的条形码进行准确识别。本文将详细介绍系统学习的流程,并提供详细教案,以帮助读者理解和实施该系统。 引言…...

F5.5G落进现实:目标网带来的光之路

数字化与智能化的世界将走向何方?这个问题有着非常复杂的答案,但其中有一个答案已经十分清晰。那就是智能化的下一步,必将走向泛在万兆的世界。 网络是算力联接的底座,是智能演化的基础。纵观每一代数字化升级,都可以发…...

Python调用c++生成的dll

Python调用c生成的dll 1.简单例子1.1 vs2019 c生成dll1.2 Python端调用 2.调用c类生成的dll2.1 vs cpp端生成dll2.2 Python端调用 参考文献 1.简单例子 1.1 vs2019 c生成dll 项目中添加add.cpp文件 extern "C" int __declspec(dllexport) add(int x, int y) {retu…...

算法基础学习|二分

二分 模板 整数二分模板 bool check(int x) {/* ... */} // 检查x是否满足某种性质// 区间[l, r]被划分成[l, mid]和[mid 1, r]时使用&#xff08;即寻找左边界使用&#xff09;&#xff1a; int bsearch_1(int l, int r) {while (l < r){int mid l r >> 1;if (…...

mac M1 pro 安装grpc 报错

pecl install grpc # a few moments later 。。。。# 执行 php -i | grep grpc## 报错 PHP Warning: PHP Startup: Unable to load dynamic library grpc.so(tried: /opt/homebrew/lib/php/pecl/20190902/grpc.so (dlopen(/opt/homebrew/lib/php/pecl/20190902/grpc.so, 0x0…...

交银国际:拼多多财报预测:主站盈利提升有望带动业绩超预期

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;交银国际今日发布关于拼多多第三季度财报预测&#xff1a;主站盈利提升有望带动业绩超预期的研报。交银国际主要观点如下&#xff1a; 预计拼多多(PDD)第三季度业绩将好于市场预期&#xff1a;我们…...