返回顶部
首页 > 资讯 > 后端开发 > 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://lsjlt.com/news/15187.html(转载时请注明来源链接)

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

猜你喜欢
  • Python的Socket编程过程中实现UDP端口复用的实例分享
    关于端口复用 一个套接字不能同时绑定多个端口,如果客户端想绑定端口号,一定要调用发送信息函数之前绑定( bind )端口,因为在发送信息函数( sendto, 或 write ),系统会自动给当前网络程序分...
    99+
    2022-06-04
    端口 过程中 复用
  • Android编程实现简单的UDP Client实例
    本文实例讲述了Android编程实现简单的UDP Client。分享给大家供大家参考,具体如下: 该代码在4.2.2内调试通过 1.记得加权限 <uses-permis...
    99+
    2022-06-06
    udp Android
  • Python利用socket实现多进程的端口扫描器
    作为开发人员经常需要查看服务的端口开启状态判断服务是否宕机。 特别是部署的服务比较多的情况下,可能存在几个甚至几十个服务端口的占用,于是我利用socket不断向服务发送请求的方式来判...
    99+
    2022-12-08
    Python socket多进程端口扫描 Python socket 端口扫描 Python 端口扫描
  • 使用Python编写简单的端口扫描器的实例分享
    单线程实现 单线程实现道理比较简单,这里尝试Soket连接3389,连接成功说明端口开放,否则说明没有开远程服务。随便修改了一下就ok了,代码如下,最终得到自己的IP地址。 #!/usr/bin/env...
    99+
    2022-06-04
    扫描器 端口 实例
  • 利用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
  • Python中基础的socket编程实战攻略
    在网络通信中socket几乎无处不在,它可以看成是应用层与TCP/IP协议簇通信的中间软件抽象层,是两个应用程序彼此进行通信的接口,并且把复杂的TCP/IP协议细节隐藏在接口之后。Python提供了sock...
    99+
    2022-06-04
    实战 攻略 基础
  • Python的Asyncore异步Socket模块及实现端口转发的例子
    Asyncore模块提供了以异步的方式写入套接字服务客户端和服务器的基础结构。 只有两种方式使一个程序在单处理器上实现“同时做不止一件事”。多线程编程是最简单和最流行的方式,但是有另一种很不一样的技术,可以...
    99+
    2022-06-04
    端口 模块 例子
  • Android编程实现调用系统分享功能示例
    本文实例讲述了Android编程实现调用系统分享功能。分享给大家供大家参考,具体如下: public class ShareActivity extends Activit...
    99+
    2022-06-06
    调用 示例 系统 Android
  • python实现的多线程端口扫描功能示例
    本文实例讲述了python实现的多线程端口扫描功能。分享给大家供大家参考,具体如下: 下面的程序给出了对给定的ip主机进行多线程扫描的Python代码 #!/usr/bin/env python #en...
    99+
    2022-06-04
    示例 多线程 功能
  • 实现SQL分页的存储过程代码分享
    这篇文章主要介绍“实现SQL分页的存储过程代码分享”,在日常操作中,相信很多人在实现SQL分页的存储过程代码分享问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”实现SQL分页的...
    99+
    2024-04-02
  • linux中socket编程常用头文件的示例分析
    这篇文章给大家分享的是有关linux中socket编程常用头文件的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。sys/types.h:数据类型定义sys/socket.h:提供socket函数及数据结构...
    99+
    2023-06-09
  • 编程算法与重定向实践:ASP 教程中的案例分享
    ASP(Active Server Pages)是一种动态网页技术,它使用 VBScript 或 JScript 等脚本语言编写网页,可以与数据库交互,并且在客户端和服务器端都可以使用。在本文中,我们将分享一些编程算法和重定向实践的案例,...
    99+
    2023-10-18
    教程 编程算法 重定向
  • Android编程中Perferences的用法实例分析
    本文实例讲述了Android编程中Perferences的用法。分享给大家供大家参考,具体如下: 浏览手机的/data/data/目录中的各个package的目录,经常会看到有...
    99+
    2022-06-06
    Android
  • shell编程中for循环语句的实现过程及案例
    目录前言示例1:批量添加用户示例2:根据IP地址检查主机状态示例3:自动生成一个8位随机密码 取值范围大小写字母和数字编写脚本应该注意的事项:总结前言 本篇是shell编程for循环的实现过程以及一些案例 什么是for循...
    99+
    2022-06-05
    Shell for循环 shell脚本for循环语句 shell中for循环语句
  • 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协程
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作