UDP bind 测试的问题

mndsoft 11月前 1004

我在用 aardio 的UDP广播功能时测试好像 UDP Bind 网卡无效,不知道是不是我的方法有问题还是这个wsock.udp 库有问题。

电脑里有2个网卡,一个以太网,一个是WLAN,我需要分别给这2个网卡广播数据,但是使用 udpClient.bind()指定的网卡IP ,服务端收到显示始终是一个IP,通过Wireshark抓包信息来看,确实客户端的网卡IP没有变化。我怀疑wsock.udp 有个bug,用其他第三方工具测试,绑定网卡时收到会显示绑定网卡IP。

以下是测试代码和截图,麻烦大佬们测试下指教一二,感谢!

Code AardioLine:94复制
  • 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.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
    • import win.ui;
    • import wsock.udp.asynClient;
    • /*DSG{{*/
    • var winform = win.form(text="UDP Bind测试";right=997;bottom=469)
    • winform.add(
    • button={cls="button";text="Bind IP 测试";left=714;top=217;right=908;bottom=260;z=5};
    • cmbAdapter={cls="listbox";left=714;top=19;right=983;bottom=110;edge=1;items={};z=4};
    • static={cls="static";text="选择网卡:";left=645;top=20;right=711;bottom=42;dl=1;dt=1;transparent=1;z=2};
    • txtIP={cls="static";text="网卡IP:";left=656;top=143;right=971;bottom=165;dl=1;dt=1;transparent=1;z=3};
    • txtLog={cls="richedit";left=5;top=7;right=625;bottom=460;bgcolor=1;db=1;dl=1;dr=1;edge=1;font=LOGFONT(h=-13;name='微软雅黑');multiline=1;readonly=1;vscroll=1;wrap=1;z=1}
    • )
    • /*}}*/
    • //创建UDP服务器
    • var udpServer = wsock.udp.asynClient();
    • //启用UDP服务器广播
    • udpServer.setBroadcast(true);
    • //udpServer.reuseAddress(true);
    • udpServer.bind("0.0.0.0",1901)
    • import inet.adapterInfo;
    • //adapterInfo方式遍历网卡
    • var loadNetworks = function(){
    • winform.cmbAdapter.clear();
    • for adapterInfo in inet.adapterInfo.each(2/*_AF_INET*/) {
    • //IP地址
    • for addr,strAddr in adapterInfo.eachUnicastAddress(){ strIP=strAddr; }
    • //判断网卡是否可用
    • if(adapterInfo.operStatusUp){ //如果可以,则添加到列表
    • //Software Loopback Interface
    • if string.left(adapterInfo.description,8) != "Software" {
    • winform.cmbAdapter.add(strIP,1)
    • }
    • }
    • }
    • if (winform.cmbAdapter.count>0) { winform.cmbAdapter.selIndex=1 }
    • }
    • //加载网卡
    • loadNetworks();
    • //显示Log信息
    • logview = function(data,color,bkcolor){
    • winform.txtLog.appendText( tostring(time(," [%H:%M:%S] ") ),data,'\r\n');
    • var line = winform.txtLog.lineCount-1;
    • var start = winform.txtLog.lineToChar(line)
    • winform.txtLog.setsel(start,-1);
    • winform.txtLog.setSelCharformat( textColor = color;backColor = bkcolor)
    • winform.txtLog.deselect();
    • winform.txtLog.lineScroll();
    • if (line>100) {
    • winform.txtLog.text="";
    • }
    • }
    • winform.cmbAdapter.onSelChange = function(){
    • winform.txtIP.text = "所选网卡IP:" ++ winform.cmbAdapter.selText
    • }
    • //接收数据
    • udpServer.onReceive = function(err){
    • var strReceive= udpServer.recvfrom(1024); //接收数据
    • var strIP = udpServer.getRemoteIp(); //远端IP
    • logview("客户端IP:" ++ strIP,0x0000FF);
    • logview("数据--->:" ++ string.hex(strReceive," "),0xFF0000);
    • }
    • //创建UDP客户端
    • var udpClient = wsock.udp.client();
    • //启用广播模式
    • udpClient.setBroadcast(true);
    • //网卡绑定测试
    • winform.button.oncommand = function(id,event){
    • //绑定当前所选IP
    • udpClient.bind(winform.cmbAdapter.selText,1901)
    • logview("Bind 网卡:" ++ winform.cmbAdapter.selText,0x00FFFF)
    • //发送测试数据
    • var strM4 ="01 02 03 04"
    • udpClient.sendto(string.unhex(strM4," "),'255.255.255.255',1901);
    • }
    • winform.show();
    • win.loopMessage();


    最新回复 (6)
    • mndsoft 11月前
      0 2

      同一个wsock.udp.client 实例只能 Bind一次 IP,切换Bind IP用的还是第一次的IP,目前临时的办法就是创建2个 实例分别绑定。这样程序处理就不通用了。

      Code AardioLine:5复制
    • 1.
    • 2.
    • 3.
    • 4.
    • 5.
      • var udpClientA = wsock.udp.client();
      • udpClientA.bind("192.168.0.93",1902)
      • var udpClientB = wsock.udp.client();
      • udpClientB.bind("192.168.1.100",1902)


      wsock.udp.asynClient() 是基于 wsock.udp.client这个库,在这个库中 估计bind这个有BUG,但初学者实力不够,不知道哪里下手修改哈。

      Code AardioLine:9复制
    • 1.
    • 2.
    • 3.
    • 4.
    • 5.
    • 6.
    • 7.
    • 8.
    • 9.
      • bind = function(ip,port){
      • if( ip === null ) ip = ..wsock.getIp();
      • var service = ..wsock.sockaddr_in( ip,port : 0 );
      • service.sin_family = 0x2/*_AF_INET*/
      • if ..wsock.bind( this.hSocket,service,..raw.sizeof(service)) =-1/*_SOCKET_ERROR*/ {
      • return null, ..wsock.err.lasterr() ;
      • }
      • return true;
      • };


      或许有人奇怪为何要 绑定2个呢,因为需要全局域网广播给设备,多网段就需要单播,场景一般用于搜索全网段的硬件设备。


    • mndsoft 11月前
      0 3

      找了一个办法就是 close 掉上一个实例,重新创建实例就可以bind了, 感觉这样反复创建不是很好,但是可以解决多网卡bind广播的问题, aardio UDP不是很熟悉,也许就是需要这样哈。

      如下:下面仅是个示例,实际会根据获取网卡IP 循环 bind即可,已经完美解决。

      Code AardioLine:15复制
    • 1.
    • 2.
    • 3.
    • 4.
    • 5.
    • 6.
    • 7.
    • 8.
    • 9.
    • 10.
    • 11.
    • 12.
    • 13.
    • 14.
    • 15.
      • var strM4 ="01 02 03 04"
      • var udpClient = wsock.udp.asynClient(); //创建异步UDP
      • udpClient.setBroadcast(true)
      • udpClient.bind("192.168.1.100",1901)
      • udpClient.sendto(string.unhex(strM4," "),"255.255.255.255",1901);
      • thread.delay(100) //稍微延时下,避免关闭过早收不到返回数据
      • udpClient.close() //关闭
      • var udpClient = wsock.udp.asynClient(); //再次创建UDP实例
      • udpClient.setBroadcast(true)
      • udpClient.bind("192.168.0.93",1901)
      • udpClient.sendto(string.unhex(strM4," "),"255.255.255.255",1901);
      • thread.delay(100) //稍微延时下,避免关闭过早收不到返回数据
      • udpClient.close() //再次关闭


    • pamir 11月前
      0 4
      谢谢大佬分享,学习了。
    • mndsoft 11月前
      0 5
      pamir 谢谢大佬分享,学习了。
      哈哈,高抬,哪里什么大佬,我也是初学者,断断续续学了一段时间,主要是搞硬件的,用aardio做一些小工具和硬件通讯挺方便。
    • Jacen 11月前
      0 6

      在其他编程语言里你也只能 bind 一次。

      一、解决问题的步骤:

      1、掌握基础语法知识,了解 aardio 函数失败会在第 2 个返回值返回错误信息。
      bind 函数的错误信息会直接告诉你答案,或者用 wsock.err.lasterr() 也能得到错误信息。

      2、这个库是开源的,没几句代码,调用的是系统函数,看微软 bind 函数的文档也有说明。

      二、觉得规则设计不完美怎么办:

      能设计操作系统、套接字、网络协议的人你可以信任。他们比我们更清楚怎样做更好。


      三、怀疑 aardio 有 bug :


      《代码大全》上有一段话,大意是编程大多数问题是程序员自己造成的,而其中大部分是最低级的笔误。一个拙劣的程序员会优先怀疑怀开发工具,而一个聪明的程序员会优先检查自己的问题。

      编程工具是不停歇制造新问题的工具,如果每个问题都怀疑是 bug ,那会先在错误的方向累垮自己。

      确实找到 bug ,我们非常欢迎,没有人愿意让 bug 留在那里不被发现。 

      但没有 bug 经常自己吓自己,误导自己走弯路是很可惜的。

    • axuanup 7月前
      0 7
      刚好用到这个,需要通过广播和组播查找设备
    返回