V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
a54552239
V2EX  ›  程序员

UDP 协议,怎么从外网推送消息到内网设备?

  •  
  •   a54552239 · 2019-05-23 14:47:48 +08:00 · 5404 次点击
    这是一个创建于 2012 天前的主题,其中的信息可能已经有所发展或是发生改变。

    PHP,云端用 workerman 做 udp 服务器。硬件设备是单片机。现在的情况是,云端服务器可以接收从内网设备发出的数据,获取动态的 IP 和端口。但是不能根据这个获取到的 IP (公网)和端口号发送数据给设备,只能用内网 IP 和端口发送。用小米路由器的端口映射可以解决,不过不灵活。因为端口号是不固定的。希望有一个好的解决方案

    39 条回复    2019-05-24 07:20:45 +08:00
    unixeno
        1
    unixeno  
       2019-05-23 14:55:30 +08:00 via Android   ❤️ 1
    可以发啊,你需要维护一个心跳包定时发,不然 nat 就老化了
    TomVista
        2
    TomVista  
       2019-05-23 15:16:39 +08:00
    不应该啊,云端按照 socket 就能发回来,你这个是不是代码出问题了
    opengps
        3
    opengps  
       2019-05-23 15:18:17 +08:00 via Android
    能去就能回的
    a54552239
        4
    a54552239  
    OP
       2019-05-23 15:20:05 +08:00
    我是指不定再某个时候主动推送消息的。不是在当前连接,当前连接的话是可以发的。
    a54552239
        5
    a54552239  
    OP
       2019-05-23 15:20:15 +08:00
    a54552239
        6
    a54552239  
    OP
       2019-05-23 15:21:08 +08:00
    设备大概是每 30 秒会向服务器推送数据
    TomVista
        7
    TomVista  
       2019-05-23 15:22:10 +08:00
    心跳包保活,
    whatsmyip
        8
    whatsmyip  
       2019-05-23 15:22:11 +08:00
    需要心跳保活,之前做 app 推送遇到过,超过 10s 链接就被关掉了,但是感知不到。
    a54552239
        9
    a54552239  
    OP
       2019-05-23 15:24:03 +08:00
    是在服务器端做心跳包吗?
    @TomVista
    @whatsmyip
    TomVista
        10
    TomVista  
       2019-05-23 15:26:28 +08:00
    客户端,要不然链接死了,服务器就丢了客户端,或者客户端 ip 动态改变了,服务器就找不到了,
    a54552239
        11
    a54552239  
    OP
       2019-05-23 15:28:41 +08:00
    现在有做心跳的,间隔 17 秒
    a54552239
        12
    a54552239  
    OP
       2019-05-23 15:28:49 +08:00
    TomVista
        13
    TomVista  
       2019-05-23 15:31:40 +08:00
    服务器接收心跳包,然后更新客户端 socket,需要主动推送,就把存的 socket 拿出来,进行推送.

    是这个套路不.
    a54552239
        14
    a54552239  
    OP
       2019-05-23 15:32:53 +08:00
    @TomVista 目前是这个套路
    TomVista
        15
    TomVista  
       2019-05-23 15:34:21 +08:00
    那怎么会接不到,,
    opengps
        16
    opengps  
       2019-05-23 15:35:49 +08:00 via Android
    给你参考下,我做的 GPS 定位器,是等待设备过来时候再下发指令,要么就通过短信这种方式下达指令
    TomVista
        17
    TomVista  
       2019-05-23 15:36:31 +08:00
    "但是不能根据这个获取到的 IP (公网)和端口号发送数据给设备,"

    存的是 socket 对象 不是 socket 里面的 ip,对吧?
    a54552239
        18
    a54552239  
    OP
       2019-05-23 15:40:30 +08:00
    @TomVista 是同一个 ip。不过我是希望某个时候,由服务器端根据这个 ip 和端口再主动和设备监理一个连接。。不懂可行不
    a54552239
        19
    a54552239  
    OP
       2019-05-23 15:41:03 +08:00
    @opengps 实时位置做持久化处理吗?
    billzhuang
        20
    billzhuang  
       2019-05-23 15:52:10 +08:00
    TomVista
        21
    TomVista  
       2019-05-23 15:53:55 +08:00
    List<Socket > socketList = new List<Socket >();
    Socket client= sc.Accept(); //服务器接收客户端 socket
    socketList .Add(client);
    socketList[0].send();//服务器利用客户端 socket 下发信息
    opengps
        22
    opengps  
       2019-05-23 15:56:06 +08:00
    @a54552239 肯定得持久化,系统要求在线轨迹不得低于 1 个月,历史轨迹不得低于 1 年的保存周期
    a54552239
        23
    a54552239  
    OP
       2019-05-23 15:56:06 +08:00
    @TomVista 应该是正解了。我改业务代码去。。。
    a54552239
        24
    a54552239  
    OP
       2019-05-23 15:56:57 +08:00
    谢谢各位的热心解答
    @a54552239
    @TomVista
    @billzhuang
    a54552239
        25
    a54552239  
    OP
       2019-05-23 15:57:23 +08:00
    感谢分享
    @billzhuang
    unixeno
        26
    unixeno  
       2019-05-23 15:59:04 +08:00 via Android
    @a54552239 UDP 不是链接的,存 socket 对象没啥用
    你按客户端给你发过来的 ip 和端口回复回去就行
    心跳的话,客户端给服务端发或者服务端给客户端发都是可以的
    mirrorman
        27
    mirrorman  
       2019-05-23 17:10:06 +08:00 via iPhone
    推测应该是客户端端口在一段时间之后挂了,你可以用其他服务器向客户端同一个端口发东西测试一下,Linux udp 底层的 socket 发到服务器是会把地址传过去的,正常的话服务器是能发回数据的
    smdbh
        28
    smdbh  
       2019-05-23 18:52:09 +08:00
    udp 不是面向连接的,不明白 ls 的大佬的思路
    tcp 不好么?
    goofool
        29
    goofool  
       2019-05-23 19:20:47 +08:00
    有几个单片机,如果只有一个可以用路由器开 DMZ
    dabaibai
        30
    dabaibai  
       2019-05-23 19:43:55 +08:00
    不行 运营商不允许这样
    a54552239
        31
    a54552239  
    OP
       2019-05-23 19:54:17 +08:00
    @smdbh 硬件提供商用的 udp
    a54552239
        32
    a54552239  
    OP
       2019-05-23 19:54:24 +08:00
    @goofool 有好几个呢
    goofool
        33
    goofool  
       2019-05-23 21:08:21 +08:00
    @a54552239 那就只能保持长连接,或者客户端轮询了
    phithon
        34
    phithon  
       2019-05-23 22:02:58 +08:00
    看看 unpn 协议吧,动态改端口映射
    phithon
        35
    phithon  
       2019-05-23 22:03:31 +08:00
    upnp 写错
    ihciah
        36
    ihciah  
       2019-05-24 00:11:16 +08:00 via iPad
    不想手动做端口映射,不想配 dmz 主机,不想用 tcp,那只有 upnp 了,前提是路由支持这东西。
    KasuganoSoras
        37
    KasuganoSoras  
       2019-05-24 03:00:04 +08:00
    推测是你的心跳包间隔时间太长,客户端那头的端口关闭了,建议把心跳包间隔时间缩短,比如 10s,或者 5s。
    可以参考我这个项目,PHP 写的聊天软件,基于 UDP: https://github.com/kasuganosoras/UChat
    理论上服务器只要按原路把数据包发回客户端的 IP 和端口是能够正确传递回去的。
    ho121
        38
    ho121  
       2019-05-24 06:53:22 +08:00 via Android
    nicevar
        39
    nicevar  
       2019-05-24 07:20:45 +08:00
    有个东西叫 stun,楼主去看一下文档就行了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5803 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 06:05 · PVG 14:05 · LAX 22:05 · JFK 01:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.