iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Python的Socket编程过程中实现UDP端口复用的实例分享
  • 352
分享到

Python的Socket编程过程中实现UDP端口复用的实例分享

端口过程中复用 2022-06-04 19:06:46 352人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

关于端口复用 一个套接字不能同时绑定多个端口,如果客户端想绑定端口号,一定要调用发送信息函数之前绑定( bind )端口,因为在发送信息函数( sendto, 或 write ),系统会自动给当前网络程序分

关于端口复用

一个套接字不能同时绑定多个端口,如果客户端想绑定端口号,一定要调用发送信息函数之前绑定( bind )端口,因为在发送信息函数( sendto, 或 write ),系统会自动给当前网络程序分配一个随机端口号,这相当于随机绑定了一个端口号,这里只会分配一次,以后通信就以这个随机端口通信,我们再绑定端口号的话,就会绑定失败。如果我们放在发送信息函数( sendto, 或 write )之前绑定,那样程序将以我们绑定的端口号发送信息,不会再随机分配一个端口号。实际上,默认的情况下,如果一个网络应用程序的一个套接字 绑定了一个端口,这时候,别的套接字就无法使用这个端口。那如何让两个套接字都能成功绑定一个端口呢?这时候就需要要到端口复用了。端口复用允许在一个应用程序可以把 n 个套接字绑在一个端口上而不出错。
端口复用能在系统已开放的端口上进行通讯,只对输入的信息进行字符匹配,不对网络数据进行任何拦截、复制类操作,所以对网络数据的传输性能丝毫不受影响。
但要注意,建立连接后服务端程序占用极少系统资源,被控端不会在系统性能上有任何察觉,通常被后门木马所利用。
在winsock的实现中,对于服务器的绑定是可以多重绑定的,在确定多重绑定使用谁的时候,根据一条原则是谁的指定最明确则将包递交给谁,而且没有权限之分,也就是说低级权限的用户是可以重绑定在高级权限如服务启动的端口上的,这是非常重大的一个安全隐患。

python解决UDP端口复用问题
一直觉得UDP协议很简单,但是今天问题让我感觉到网络的基础真是博大精深。

废话少说,来看问题吧。由于协议的需要,我得实现一个UDP的客户端和服务器端,并且从同一个端口读写数据。

最初不以为然,无非就是用两个Socket,一个监听并从这个端口读取数据(服务器端采用了twisted),另一个向这个端口写入数据,用Python实现只要10行左右的代码。


def startServer(queue, port): 
  Reactor.listenUDP(port, DhtResponseHandler(queue)) 
  reactor.run() 

def sendUdpMsg(self, addr, msg): 
  socketHandler = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
  socketHandler.bind(("", self.port)) 
  socketHandler.sendto(msg, addr) 
  socketHandler.close() 

由于要向同一个端口写数据,于是client必须有bind,但是运行后发现server先bind了这个端口,client运行时会报错

error: [Errno 10048] Only one usage of each socket address (protocol/network address/port) is nORMally permitted


一般这种错误时因为多个socket不能同时bind同一个地址
由于基础不够扎实,我开始疯狂的搜索,发现有人说端口复用的问题,所谓的端口复用,是指一个套接字释放掉一个端口后有一个wait_time,另一个套接字如果接着bind就会报错。虽然我的问题不完全一样,但是我欣喜若狂的使用了。即在client bind前加上如下一句


socketHandler.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 

但是仍然报错:

error: [Errno 10013] An attempt was made to access a socket in a way forbidden by its access permissions


(顺便一提,还有另一个参数叫SO_REUSEPORT,即复用端口,另外有一个叫SO_EXCLUSIVEADDRUSE,即不准复用该端口,其他socket的参数还有很多,可以参考winsockHttp://msdn.microsoft.com/en-us/library/aa924071.aspx或者unix下的socket)
这个10013错误让我百思不得其解,搜索一下,主要有两种解释,有人说是需要提升应用程序的权限为管理员,我用的是eclipse+pydev,提升完eclipse权限没用,实际上还要修改python.exe的权限,方法是在这个程序上右键,兼容性一栏中勾上以系统管理员身份运行;有人说是跟其他程序地址或者端口冲突。但是我测试过发现都不行。

另外,运行的时候发现,twisted的服务器端一定是要在主线程中,否则会报signal一定要在主线程才能接受的错误,但是twisted的reactor一运行起来就阻塞了。

在twisted文档中翻到,原来还有一种UDP叫做connected UDP,变态吧,所谓connected UDP,就是只能向一个地址收发数据,看起来貌似可以,但是不符合可以向多个地址接收数据。

最后在一篇文章中翻到说需要两个端口都设置重用,于是我试着重新写一个服务器,与之前的客户端配合,运行良好,完全无错


sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
sock.bind(("", port)) 
data, address = sock.recvfrom(4096) 

好吧,看来问题在调用twisted了,不知道他是否有这样的设置,进去将这部分代码翻了一下,找不到这样设置的参数。


class Port(abstract.FileHandle): 
  def __init__(self, port, proto, interface='', maxPacketSize=8192, 
         reactor=None): 
    """ 
    Initialize with a numeric port to listen on. 
    """ 
    self.port = port 
    self.protocol = proto 
    self.readBufferSize = maxPacketSize 
    self.interface = interface 
    self.setLogStr() 
    self._connectedAddr = None 
 
    abstract.FileHandle.__init__(self, reactor) 
 
    skt = socket.socket(self.addressFamily, self.socketType) 
    addrLen = _iocp.maxAddrLen(skt.fileno()) 
    self.addressBuffer = _iocp.AllocateReadBuffer(addrLen) 
    # WSARecvFrom takes an int 
    self.addressLengthBuffer = _iocp.AllocateReadBuffer( 
        struct.calcsize('i')) 
 
  def startListening(self): 
    """ 
    Create and bind my socket, and begin listening on it. 
 
    This is called on unserialization, and must be called after creating a 
    server to begin listening on the specified port. 
    """ 
    self._bindSocket() 
    self._connectToProtocol() 
 
 
  def createSocket(self): 
    return self.reactor.createSocket(self.addressFamily, self.socketType) 
 
 
  def _bindSocket(self): 
    try: 
      skt = self.createSocket() 
      skt.bind((self.interface, self.port)) 
    except socket.error, le: 
      raise error.CannotListenError, (self.interface, self.port, le) 
 
    # Make sure that if we listened on port 0, we update that to 
    # reflect what the OS actually assigned us. 
    self._realPortNumber = skt.getsockname()[1] 
 
    log.msg("%s starting on %s" % ( 
        self._getLogPrefix(self.protocol), self._realPortNumber)) 
 
    self.connected = True 
    self.socket = skt 
    self.getFileHandle = self.socket.fileno 

难道说twisted就完全不提供这样的功能?最终在multicast中翻到这样一段,也就是,多播的情况是支持地址复用的,动手测起来。


class MulticastPort(MulticastMixin, Port): 
  """ 
  UDP Port that supports multicasting. 
  """ 
 
  implements(interfaces.IMulticastTransport) 
 
 
  def __init__(self, port, proto, interface='', maxPacketSize=8192, 
         reactor=None, listenMultiple=False): 
    Port.__init__(self, port, proto, interface, maxPacketSize, reactor) 
    self.listenMultiple = listenMultiple 
 
 
  def createSocket(self): 
    skt = Port.createSocket(self) 
    if self.listenMultiple: 
      skt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
      if hasattr(socket, "SO_REUSEPORT"): 
        skt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) 
    return skt 

将server端改成如下代码,运行通过!


reactor.listenMulticast(port, DhtResponseHandler(queue), listenMultiple=True) 
reactor.run() 

感触良多,底层的知识比较重要,浮沙筑高台果然危险。

--结束END--

本文标题: Python的Socket编程过程中实现UDP端口复用的实例分享

本文链接: https://www.lsjlt.com/news/15187.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Python利用socket实现多进程的端口扫描器
    作为开发人员经常需要查看服务的端口开启状态判断服务是否宕机。 特别是部署的服务比较多的情况下,可能存在几个甚至几十个服务端口的占用,于是我利用socket不断向服务发送请求的方式来判...
    99+
    2022-12-08
    Python socket多进程端口扫描 Python socket 端口扫描 Python 端口扫描
  • 利用Python实现端口扫描器的全过程
    目录socket概念 socket基本用法 创建tcp套接字 创建udp套接字 socket内建方法实现端口扫描 总结socket概念 socket又称套接字,可以看做是不同主机之...
    99+
    2024-04-02
  • Python中面向接口编程实例分析
    这篇文章主要讲解了“Python中面向接口编程实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python中面向接口编程实例分析”吧!前言接口在软件工程扮演重要角色,随着应用程序的功能...
    99+
    2023-06-30
  • 怎么在python中利用UDP编程实现通信
    今天就跟大家聊聊有关怎么在python中利用UDP编程实现通信,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。python主要应用领域有哪些1、云计算,典型应用OpenStack。2、...
    99+
    2023-06-14
  • Python中怎么使用Socket实现网络编程
    本篇文章为大家展示了Python中怎么使用Socket实现网络编程,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Socket:套接字套接字好比电话的插口,主机和端口就好比区号和电话号码,主机:是你要...
    99+
    2023-06-17
  • 实现SQL分页的存储过程代码分享
    这篇文章主要介绍“实现SQL分页的存储过程代码分享”,在日常操作中,相信很多人在实现SQL分页的存储过程代码分享问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”实现SQL分页的...
    99+
    2024-04-02
  • 编程算法与重定向实践:ASP 教程中的案例分享
    ASP(Active Server Pages)是一种动态网页技术,它使用 VBScript 或 JScript 等脚本语言编写网页,可以与数据库交互,并且在客户端和服务器端都可以使用。在本文中,我们将分享一些编程算法和重定向实践的案例,...
    99+
    2023-10-18
    教程 编程算法 重定向
  • linux中socket编程常用头文件的示例分析
    这篇文章给大家分享的是有关linux中socket编程常用头文件的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。sys/types.h:数据类型定义sys/socket.h:提供socket函数及数据结构...
    99+
    2023-06-09
  • Java使用线程池实现socket编程的方法详解
    目录前言一、一个简单的C/S模型实现1.服务器:2.客户端:二、线程池使用方法1.新建一个线程池2.用Runnable接口实现线程3.创建线程对象并提交至线程池执行三、结合起来四、使...
    99+
    2024-04-02
  • python中threading实现线程的示例分析
    小编给大家分享一下python中threading实现线程的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!过程说明从Thread类构成子类。覆盖方法根据需...
    99+
    2023-06-20
  • Python协程的2种实现方式分享
    目录什么是协程生成器协程原生协程两种协程对比实战案例什么是协程 在 Python 中,协程(Coroutine)是一种轻量级的并发编程方式,可以通过协作式多任务来实现高效的并发执行。...
    99+
    2023-05-18
    Python实现协程方式 Python实现协程 Python协程
  • 响应式编程:PHP教程中的算法实践分享。
    响应式编程是一种面向数据流和变化传播的编程范式。它的目的是使代码更加可读、可维护和可扩展。PHP作为一种流行的后端语言,也可以使用响应式编程来增强代码的质量。在本篇文章中,我们将介绍响应式编程的概念和在PHP中的实践经验。 响应式编程的...
    99+
    2023-07-22
    教程 编程算法 响应
  • 实时 Linux Shell 中使用 Python 进行网络编程的技巧分享。
    实时 Linux Shell 中使用 Python 进行网络编程的技巧分享 随着计算机科学的不断发展,网络编程已成为了一个重要的领域。在实时 Linux Shell 中使用 Python 进行网络编程的技巧,可以帮助开发者更加高效地实现网络...
    99+
    2023-09-24
    实时 linux shell
  • java编程实现简单的网络爬虫示例过程
    本项目中需要用到两个第三方jar包,分别为 jsoup 和 commons-io。 jsoup的作用是为了解析网页, commons-io 是为了把数据保存到本地。 1.爬取贴吧 第...
    99+
    2024-04-02
  • Java中的线程如何实现通过关闭Socket终止
    这篇文章将为大家详细讲解有关Java中的线程如何实现通过关闭Socket终止,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。具体内容如下package Threads;import java....
    99+
    2023-05-31
    java socket 终止线程
  • 使用nginx实现端口映射的教程
    这篇文章主要讲解了“使用nginx实现端口映射的教程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“使用nginx实现端口映射的教程”吧!考虑这样一个场景,我们部署了若干web应用在一台云服务...
    99+
    2023-06-04
  • 使用Vue3+ElementPlus前端实现分片上传的全过程
    目录1. 什么是分片上传2. 上传组件模板3. 上传组件逻辑3.1 基本思路3.2 选择上传文件3.3 校验文件是否合法3.4 文件加密3.5 合并文件3.6 文件切片上传...
    99+
    2022-11-13
    vue3 elementplus分片上传 前端文件上传 vue3 elementplus上传
  • Python与Matlab混合编程的实现案例
    目录前言一、环境准备二、简单示例三、更复杂的示例1.调用.m文件2.调用自定义函数3.绘图测试四、项目相关前言 因为项目需要,需要批处理很多Matlab的.m文件,从每个文件中提取结...
    99+
    2023-01-28
    Python与Matlab混合编程 Python Matlab混合编程
  • JavaScript中的函数式编程实例分析
    这篇文章主要介绍“JavaScript中的函数式编程实例分析”,在日常操作中,相信很多人在JavaScript中的函数式编程实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JavaScript中的函数式...
    99+
    2023-07-05
  • 实时接口在 Python 编程算法中的应用案例有哪些?
    Python 是一种广泛使用的编程语言,它非常适合进行算法编程。在 Python 编程中,实时接口是一个非常重要的概念。实时接口可以帮助程序员获取实时数据,并且将这些数据应用到算法中。在本文中,我们将探讨实时接口在 Python 编程算法中...
    99+
    2023-10-02
    编程算法 接口 实时
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作