NB-IoT使用笔记(5)在linux下用python搭建UDP转发服务器扩展NB可访问IP个数

背景

由于NB-IoT模块仅能绑定有限个IP地址,虽然个数一般情况是够用的,然而往往有些意想不到的情况下我们需要访问那些没有绑定的IP。 
为了解决这个问题,可以采用UDP转发的方式,起初使用B5电信测试卡时一直借用一个电信的udp转发服务器(或许不是电信的,相关文档地址:UDP转发网关数据格式详解-CSDN下载),数据格式=数据头(含需要转发的IP与PORT信息)+原始数据,但是有一个缺点是这个服务器提供的转发服务会将数据头一并发给需要转发的服务器。 
为了解决这个问题,在NB-IoT使用笔记(3)在linux下使用python搭建UDP服务的代码基础上,使用python在centos服务器上实现了一个可以输出log信息的UDP转发服务。


预备知识

如果看了上面一篇文章这个就不用看了O(∩_∩)O哈哈~ 
起码有下面的基础知识吧~

  • linux掌握系统的基本操作
  • python语言编程
  • udp服务的理解

在这里,提一下UDP转发的相关内容,由于NB-IoT现在只能向已经绑定的几个IP发送数据包,如果有连接多余这个个数的IP地址的需求的话,需要一个UDP转发的中间服务器负责进行数据转发,具体文档我已经上传到了UDP转发网关数据格式详解-CSDN下载,由需要的童鞋可以下载下来看看~ 
这里我贴出需要用到部分的截图: 
先是发送数据包的格式: 
这里写图片描述 
接收数据包格式: 
这里写图片描述 
最最最后,最开始测试的时候,不建议直接使用NB-IoT模块去测试,毕竟两边现在都还没完事,推荐大家使用一些网络调试助手之类的小工具,简单易用,一搜就有~


代码

一如既往地简单粗暴,先来代码:

#!/usr/bin/env python
# -*- coding:utf8 -*-

import sys
import time
import os
from time import sleep
import socket
reload(sys)
sys.setdefaultencoding('utf-8')
# make a copy of original stdout route
stdout_backup = sys.stdout
# define the log file that receives your log info
log_file = open("forward_message.log", "a")
# redirect print output to log file
sys.stdout = log_file
log_file.close()


def showHex(s):
    for c in s:
        print("%x"%(ord(c))),
    print("\nreceive length :%d"%(len(s)))

class UdpServer(object):
      def tcpServer(self):
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.bind(('', 8010))       # 绑定同一个域名下的所有机器

        while True:
            recvData, (remoteHost, remotePort) = sock.recvfrom(1024)
            log_file = open("forward_message.log", "a")
            sys.stdout = log_file
            print "****************************"
            print time.strftime("%Y-%m-%d %X",time.localtime(time.time()))
            print("[%s:%s] connect" % (remoteHost, remotePort))     # 接收客户端的ip, port
            if len(recvData)>6:
                showHex(recvData)
                print "recvData     :", recvData
                print "recvData(sub):", recvData[6:]

                sendPort = ord(recvData[4])+ord(recvData[5])*256
                sendAddr = "%d.%d.%d.%d"%(ord(recvData[0]),ord(recvData[1]),ord(recvData[2]),ord(recvData[3]))
                print ("to:%s:%d"%(sendAddr,sendPort))
                #rx after tx
                sock2 = socket.socket(socket.AF_INET,type=socket.SOCK_DGRAM)
                sock2.settimeout(None)
                sock2.sendto(recvData[6:], (sendAddr, sendPort))
                data2 = sock2.recv(512)
                #combine head and data
                data2 = '%s%s'%(recvData[:6],data2)
                sock2.close()
                print 'forward ok' 
                sendDataLen = sock.sendto(data2, (remoteHost, remotePort))
                print ("return length:%d"%(len(data2)))
            else:
                print "recvData: ", recvData
                sendDataLen = sock.sendto(recvData, (remoteHost, remotePort))
                print "sendDataLen: ", sendDataLen
                #print("sendData(%3d):%s"%(sendDataLen,recvData))
            print "****************************"
            print "\n"
            log_file.close()
            sys.stdout = stdout_backup
        sock.close()

if __name__ == "__main__":
    udpServer = UdpServer()
    udpServer.tcpServer()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

当然在接收的数据不足6个字节会直接返回。 
万事俱备只欠东风,接下来就愉快地运行程序吧,linux命令行输入:

nohup python fu_server_log.py &
  • 1

这里使用 nohup 运行命令可以使得程序在用户退出Telnet后仍然运行,后面的 & 可以让程序运行在后台(用户仍然可以在命令行运行命令,fgbg可以实现前后台任务切换),注意两者的区别,如果不加 nohup 无论程序在不在后台执行当执行 logout 退出后服务就不存在了,即程序作为子进程伴随着用户父进程被杀死。


运行测试

这里使用工具 TCP-UDP服务管理器 V3.20,首先建立一个UDP的client连接,输入IP和PORT,协议类型选择UDP : 
这里写图片描述
连接后选择否,这里发送一个DNS解析的包,向114.114.114.144:53查询baidu.com的ip地址,需要设置数据头: 
727272723500 
数据: 
D40E0100000100000000000005626169647503636F6D0000010001 
将数据头和数据部分复制到发送区1,勾选16进制发送以及16进制显示后点击发送,结果如下: 
这里写图片描述

查看服务器的log信息,在同一目录下执行:

vim forward_message.log
  • 1

这里写图片描述 
33字节接收和81字节接收符合规范~ 
使用NB-IoT测试DNS解析函数: 
这里写图片描述 
左边为发送和接收的NB-IoT模块数据,右边为函数调用结果,返回IP以及个数。


最最最最后,欢迎小伙伴们交流,一起学习

转载请注明出处

转自https://blog.csdn.net/a1668659995/article/details/78668553

猜你喜欢

转载自blog.csdn.net/sim_stone/article/details/80354379