SSDP协议的Python示例「建议收藏」

SSDP协议的Python示例「建议收藏」废话少说,直接上代码。服务端ssdp_server.py

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

废话少说,直接上代码。服务端ssdp_server.py:

# -*- coding: utf-8 -*-

import socket

SSDP_ADDR = '239.255.255.250'
SSDP_PORT = 1900
SERVICE_NAME = 'my_service'


class Connection():
    def __init__(self, s, data, addr):
        self.__s = s
        self.__data = data
        self.__addr = addr
        self.is_find_service = False

    def handle_request(self):
        if self.__data.startswith('M-SEARCH * HTTP/1.1\r\n'):
            self.__handle_search()
        elif self.__data.startswith('HTTP/1.1 200 OK\r\n'):
            self.__handle_ok()

    def __handle_search(self):
        props = self.__parse_props(['HOST', 'MAN', 'ST', 'MX'])
        if not props:
            return

        if props['HOST'] != '%s:%d' % (SSDP_ADDR, SSDP_PORT) \
                or props['MAN'] != '"ssdp:discover"' \
                or props['ST'] != 'ssdp:all':
            return

        print 'RECV: %s' % str(self.__data)
        print 'ADDR: %s' % str(self.__addr)

        response = 'HTTP/1.1 200 OK\r\nST: %s\r\n\r\n' % SERVICE_NAME
        self.__s.sendto(response, self.__addr)

    def __handle_ok(self):
        props = self.__parse_props(['ST'])
        if not props:
            return

        if props['ST'] != SERVICE_NAME:
            return

        print 'RECV: %s' % str(self.__data)
        print 'ADDR: %s' % str(self.__addr)
        print 'Find service!!!!'

        self.is_find_service = True

    def __parse_props(self, target_keys):
        lines = self.__data.split('\r\n')

        props = {}
        for i in range(1, len(lines)):
            if not lines[i]:
                continue

            index = lines[i].find(':')
            if index == -1:
                return None

            props[lines[i][:index]] = lines[i][index + 1:].strip()

        if not set(target_keys).issubset(set(props.keys())):
            return None

        return props

class SSDPServer():
    def __init__(self):
        self.__s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.__s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        local_ip = socket.gethostbyname(socket.gethostname())
        any_ip = '0.0.0.0'

        # 绑定到任意地址和SSDP组播端口上
        self.__s.bind((any_ip, SSDP_PORT))

        # INFO: 使用默认值
        # self.__s.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, 20)
        # self.__s.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1)
        # self.__s.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF,
        #                     socket.inet_aton(intf) + socket.inet_aton('0.0.0.0'))
        # INFO: 添加到多播组
        self.__s.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP,
                            socket.inet_aton(SSDP_ADDR) + socket.inet_aton(local_ip))
        self.local_ip = local_ip

    def start(self):
        while True:
            data, addr = self.__s.recvfrom(2048)
            conn = Connection(self.__s, data, addr)
            conn.handle_request()
        self.__s.setsockopt(socket.SOL_IP, socket.IP_DROP_MEMBERSHIP,
                            socket.inet_aton(SSDP_ADDR) + socket.inet_aton(self.local_ip))
        self.__s.close()

if __name__ == '__main__':
    port = SSDPServer()
    port.start()

客户端ssdp_client.py:

# -*- coding: utf-8 -*-

import socket
import time
import select
import ssdp_server

SSDP_ADDR = '239.255.255.250'
SSDP_PORT = 1900

MS = 'M-SEARCH * HTTP/1.1\r\nHOST: %s:%d\r\nMAN: "ssdp:discover"\r\nMX: 2\r\nST: ssdp:all\r\n\r\n' \
     % (SSDP_ADDR, SSDP_PORT)


class SSDPClient():
    def __init__(self):
        self.__s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

        # INFO: 若绑定,服务端收到的是固定的地址和端口号
        self.__s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        local_ip = socket.gethostbyname(socket.gethostname())
        self.__s.bind((local_ip, 50000))

    def start(self):
        self.__send_search()
        while True:
            reads, _, _ = select.select([self.__s], [], [], 5)
            if reads:
                data, addr = self.__s.recvfrom(2048)
                conn = ssdp_server.Connection(self.__s, data, addr)
                conn.handle_request()
                if conn.is_find_service:
                    break
            else:  # timeout
                self.__send_search()
        self.__s.close()

    def __send_search(self):
        print "Sending M-SEARCH..."
        # INFO: 发送到SSDP组播地址上
        self.__s.sendto(MS, (SSDP_ADDR, SSDP_PORT))

if __name__ == '__main__':
    port = SSDPClient()
    port.start()

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/183233.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mac 安装brew

    mac 安装brew

    2022年2月19日
    54
  • 列车调度问题PTA

    列车调度问题PTA7-20列车调度(25分)火车站的列车调度铁轨的结构如下图所示。两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。在图中有9趟列车,在入口处按照{8,4,2,5,3,9,1,6,7}的顺序排队等待进入。如果要求它们必须按序号递减的顺序从出口离开,则至少需要多少条平行铁轨用于调度?输入格…

    2022年7月14日
    14
  • 完美解决Spring@Autowired无法注入AbstractInterceptor

    完美解决Spring@Autowired无法注入AbstractInterceptor今天在使用AbstractInterceptor拦截时,发现Spring@Autowired无法注入,返回结果为null。捣腾了下,手动配置了下,完美解决。直接上图首先建立一个获取工厂的帮助类:在application配置文件配置我们要用的bean:配置好后,直接调用:好了,该写下一个bug了。。。。。。…

    2022年5月14日
    34
  • Python字符串与时间相互转换

    Python字符串与时间相互转换1、字符串转日期/时间注意,字符串格式要与参数中时间格式要严格匹配,否则异常举例:①2019-05-0112:00:00对应%Y-%m-%d%H:%M:%S②2019-05-01对应%Y-%m-%d2、日期/时间转字符串3、打印系统当前时间代码如下:#coding:utf-8importdatetimeimpor…

    2022年5月20日
    34
  • XSRF 防御「建议收藏」

    XSRF 防御「建议收藏」#XSRF防御#需求分析XSRF又名CSRF(opensnewwindow),跨站请求伪造,它是前端常见的一种攻击方式,我们先通过一张图来认识它的攻击手段。CSRF的防御手段有很多,比如验证请求的referer,但是referer也是可以伪造的,所以杜绝此类攻击的一种方式是服务器端要求每次请求都包含一个token,这个token不在前端生成,而是在我们每次访…

    2022年5月19日
    29
  • 操作系统——银行家算法

    操作系统——银行家算法自从写完第一篇博客,发现写博客也挺好玩的,比平时写word应付作业有趣的多,而且文章在网上还能帮助别人,自己平时也经常看CSDN,这不,老师要求我们实现一下操作系统的银行家算法,所以我就来了!那么,什么是银行家算法呢?如果你很了解请跳过这一段,就是解决死锁问题的一个算法,是由艾兹格·迪杰斯特拉在1965年为T.H.E系统设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判…

    2022年7月22日
    7

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号