DatagramPacket packet = new DatagramPacket(buf, buf.length, addr, port);这句中的addr,和port是指定open的地址,端口的!如果没有当然会出错!

解决方案 »

  1.   

    至于你send了但对方收不到,这才是说明了UDP得特征:就是不可靠性!(谁说过数据包时面相无联结的!?它只是为了效率降低了一点可靠性的SOCKET)
    给你一段话:<thinking java>
    TCP根据该协议的
    设计宗旨,它具有高度的可靠性,而且能保证数据顺利抵达目的地。换言之,它允许重传那些由于各种原因
    半路“走失”的数据。而且收到字节的顺序与它们发出来时是一样的。当然,这种控制与可靠性需要我们付
    出一些代价:TCP 具有非常高的开销。
    还有另一种协议,名为“用户数据报协议”(UDP),它并不刻意追求数据包会完全发送出去,也不能担保它
    们抵达的顺序与它们发出时一样。我们认为这是一种“不可靠协议”(TCP 当然是“可靠协议”)。听起来
    似乎很糟,但由于它的速度快得多,所以经常还是有用武之地的。对某些应用来说,比如声音信号的传输,
    如果少量数据包在半路上丢失了,那么用不着太在意,因为传输的速度显得更重要一些。
      

  2.   

    我这里省略了一下,addr,port是对方的IP和端口,只要对方程序在运行,这些代码都没有问题,但若对方不在运行,一但调用sock.send,在sock.receive就会抛出一个异常:
    java.net.SocketException: Connection reset by peer: Datagram peek failed
    但数据报不是面向无连接的吗,对方收不到应该不作任何处理才对呀,我的sock只绑定了本地接收端口,sock.receive应该可以接收任何地方发来的数据报,为什么会出现这个异常呢?
      

  3.   

    UDP协议是面向无连接的,但是系统一般都提供connect方法,目的是绑定目标主机和端口。方法调用成功并不表示本机与目标机已经建立物理连接,而只是在本机操作系统中注册了一下。以后本UDP端口将不发送或接收除了已绑定了的目标主机端口的任何数据报。请参阅W.Richard Stevens《UNIX网络编程 第一卷》第8、25章。
      

  4.   

    如果receive收不到应该阻塞的,不应该出错。你的send和receive什么关系?为什么调send,receive也运行?
      

  5.   

    我试了一个上午,大概弄清楚什么回事了,我的send和receive是用同一个sock,其中receive是在一个线程的一个死循环内不停调用的,当没有数据时receive被阻塞,当我用send向一个不存在的对端发送时,可能由于IP协议会返回表示目的不可达的ICMP包,此时receive就抛出了Datagram peek failed的异常。
    我将send和receive分用两个DatagramSocket实现,就不会出现这个异常了。
    但是按UDP协议,当目的不可达时不应该作任何处理,我用C编的程序中就不会出现这种情况。本来我是想用一个socket就实现与所有客户端的通信,现在必须对每个客户端都创建一个socket才行了。
    不知那位高手有这方面的经验,这样解决最好?
      

  6.   

    我在1.4/1.3.1+Win2000下试验,用同一个socket没有这个错误,恐怕还有别的原因吧,你的版本是多少?
      

  7.   

    我是用jdk1.31+win2000,刚做了一个简单例子,帮助说明问题:
    //UdpTest.java
    import java.net.*;
    import java.io.*;public class UdpTest {
        public static void main(String[] args) {
            DatagramSocket sock = null;
            byte[] buf1 = new byte[1000];
            DatagramPacket packet1 = new DatagramPacket(buf1, buf1.length);
            byte[] buf2 = new byte[1000];
            InetAddress addr = null;
            
            try {
                sock = new DatagramSocket(8888);
                System.out.println("start");
                
                try {
                    addr = InetAddress.getByName("localhost");
                } catch (UnknownHostException e) {
                    System.out.println(e);
                }
                DatagramPacket packet2 = new DatagramPacket(buf2, buf2.length, addr, 9999);
                sock.send(packet2);
                
                sock.receive(packet1);
            } catch (SocketException e) {
                System.out.println("sock error:"+e);
                e.printStackTrace();
            } catch (IOException e)  {
                System.out.println("io error:"+e);
                e.printStackTrace();
            } finally {
                sock.close();
            }
        }
    }运行后马上报告异常,若把sock.send(packet2)注释掉,则程序阻塞在sock.receive。
    若先在本机启动另一socket通信程序,侦听UDP端口9999,再运行本程序则一切正常。
      

  8.   

    我说的参考资料你有没有看?对方机器没有程序在端口上接收的话,对方机器会返回一个“目标不可到达”的ICMP包,本地主机接收到该包后一般会把它丢弃,只有两种情况例外,一:你的UDP SOCKET是已经“connect”到对方机器的端口上的;二:本地主机操作系统是win2000,它会把该ICMP包发送给应用程序,导致JAVA的receive方法抛出一个“socket已关闭”的例外;所以在win2000上肯定会存在你提到的问题,同样的程序在NT和UNIX上都正常。这是我在以前一个项目中测了好多台机器(包括3台win2000,3台NT,1台HP UNIX, 1台SOLARIS)得出的结论。
      

  9.   

    恩,hyhong_h(黄黄)说的第二个情况是原因所在,不过这个问题在1.4中已经得到了修正。另外在其他版本中如果你在receive出错后再receive一次也能继续。