UDP bind 测试的问题

mndsoft 3月前 358

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

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

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

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();


最新回复 (5)
  • mndsoft 3月前
    0 2

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

    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,但初学者实力不够,不知道哪里下手修改哈。

    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 3月前
    0 3

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

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

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

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

    一、解决问题的步骤:

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

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

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

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


    三、怀疑 aardio 有 bug :


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

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

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

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

返回