Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java DatagramSocket(UDP套接字)仅在以前发送数据包时接收_Java_Sockets_Network Programming_Udp_Voip - Fatal编程技术网

Java DatagramSocket(UDP套接字)仅在以前发送数据包时接收

Java DatagramSocket(UDP套接字)仅在以前发送数据包时接收,java,sockets,network-programming,udp,voip,Java,Sockets,Network Programming,Udp,Voip,我有以下问题: 我有一个非常简单的Java数据报客户端和服务器,位于远程机器上。客户机将不会从服务器接收任何信息,除非它提前向服务器发送数据包(数据包包含什么信息无关紧要) 以下是我的客户的样子: public static void TheClient() throws Exception { ds = new DatagramSocket(clientPort); while(true) { DatagramPacket

我有以下问题:

我有一个非常简单的Java数据报客户端和服务器,位于远程机器上。客户机将不会从服务器接收任何信息,除非它提前向服务器发送数据包(数据包包含什么信息无关紧要)

以下是我的客户的样子:

    public static void TheClient() throws Exception { 
        ds = new DatagramSocket(clientPort); 
        while(true) { 
            DatagramPacket p = new DatagramPacket(buffer, buffer.length);   
            ds.receive(p); 
            System.out.println(new String(p.getData(), 0, p.getLength())); 
        } 
    } 
基本上,它所做的就是监听端口clientPort,然后打印它接收到的任何内容。但是,它不起作用

现在,稍微修改它就可以解决问题:

public static void TheClient() throws Exception {
    ds = new DatagramSocket(clientPort); 

    //Sending an empty packet
    byte tempBuffer1[] = new byte[10];
    InetAddress address = InetAddress.getByName(SERVER_IP);
    DatagramPacket packet1 = new DatagramPacket(
            tempBuffer1, tempBuffer1.length, address, serverPort);
    ds.send(packet1);

    while(true) { 
        DatagramPacket p = new DatagramPacket(buffer, 
                buffer.length);     
        ds.receive(p); 
        System.out.println(new String(p.getData(), 0, 
                p.getLength())); 
    } 
} 
有人知道是什么导致了这个问题吗?虽然解决方案确实解决了这个问题,但对我来说没有任何意义,为什么它最初不起作用,所以解决方案可能不会在所有计算机上都起作用


另外,应该注意,当客户机和服务器都在同一台机器上时,代码工作正常

检查您的电脑是否使用私有IP地址,通常以“10.x.x.x”或“192.168.x.x”开头。如果是这样,最可能的原因是您使用的是基于NAT的防火墙,它共享一个公共地址和多个私有地址


当您向出站发送数据包时,防火墙知道应该接收返回数据包的内部地址。但是,当从外部地址启动连接时,它无法知道哪个内部地址应该接收流量。大多数SOHO(小型办公室/家庭办公室)路由器将允许您将流量“端口转发”到特定的内部IP地址。如果您使用的是DHCP,您需要为自己分配一个静态IP地址,或者您的端口转发可能会在将来某个日期停止工作,因为它会获取不同的IP地址。

这种情况发生在
AWS EC2
上。客户端的端口未在防火墙(安全组)上打开。当您的客户机向服务器发送数据包时,防火墙允许在短时间内从服务器接收数据。如果防火墙上的客户端端口已打开,则客户端可以从服务器接收,而无需向服务器发送任何内容。

您是否确定有问题的客户端节点上没有防火墙?有些防火墙会自动打开UDP返回流量,但只有在客户端首先启动时才会打开。我只是在防火墙中添加了一条规则,允许所有连接到该UDP端口,但这并没有解决问题。此外,其他使用UDP的应用程序(如Skype)在我的机器上运行良好,无需调整任何防火墙设置。我更愿意在编程方面尽可能多地做。你确定服务器正在向你发送数据包吗?是的,我100%肯定,因为当我只向客户端添加这4行代码时,一切正常。在localhost上一切都很好(即使没有这4行代码)。我也可以发布服务器代码,但我认为这是多余的。您是否只是在本地计算机的防火墙中添加了一个规则,或者是否还有一个网关(路由器等),您可以添加一个规则(或端口转发)?但要进行端口转发,我需要进入路由器的设置,显然我不能要求我的应用程序的所有用户都这样做。您是否知道从Java代码中实现这一点的方法?例如,我前面提到的skype不要求用户打开任何端口转发,但它工作正常。如果通信不是由客户端发起的,并且客户端似乎被允许位于NAT路由器后面,很可能是一个动态IP地址,那么您的“服务器”如何知道“客户端”的IP地址??这听起来很合理,通信应该由客户端发起,因此消除了您原来的问题。在我提供的示例中,我对客户端的IP进行了硬编码,但是,在我的实际应用程序中,我使用TCP套接字发送IP。此外,根据Java文档中的描述,DatagramSockets应该在不启动连接的情况下工作。Skype等应用程序围绕NAT服务器工作的一种方式是使用公共服务器代理客户端之间的连接。客户机A希望与客户机B交谈/聊天/视频/游戏,但他们的防火墙阻止他们发起对话。公共地址上的服务器C可以由两者寻址。每个客户机都会打开与服务器的连接并保持其打开状态。然后,它可以在两个客户端之间中继数据包,或者使用类似STUN的协议来执行切换,从而允许客户端直接通信。@phatfingers我在某种程度上假设Skype(或任何其他视频/语音流软件)使用UDP发送和接收数据。但是,是的,在读了一点之后,客户端接收数据似乎通常是通过TCP或其他协议完成的(除非没有防火墙)。无论哪种情况,您最初的响应都为我节省了大量时间,我通过切换到仅使用UDP向服务器发送数据和使用TCP接收数据,解决了应用程序中的问题。多谢各位!你不知道这有多大帮助。