java - 为什么 DatagramPacket 对象在使用其方法之一时会卡住?

标签 java multithreading sockets udp packet

我正在使用服务器和客户端通过 UDP 数据包共享信息。
客户端组装数据包并将其发送到服务器。
服务器接收数据包,并发出一个线程来处理它

在线程代码中,我尝试使用数据包,但我使用的每种方法都陷入困境: getAddress() 、 getData() 等
当我尝试在服务器代码中使用数据包的方法时 - 它不会卡住。仅在线程中。
我不明白为什么在线程代码中使用数据包时会卡住

这是代码,它可以编译:
客户

public class ExchangeClientProgram
{
    public final double ERROR = 0;
    private DatagramPacket packet;
    private DatagramSocket socket;
    private InetAddress hostAddress;
    private int port;
    private byte [] buf;

    public ExchangeClientProgram(String hostIp , int port) throws SocketException, UnknownHostException
    {
        this.port = port;
        socket = new DatagramSocket();
        hostAddress = InetAddress.getByName(hostIp);

    }

    public boolean sendRequestPacket(ExchangeRequest exchangeRequest)
    {
        try
        {
            buf = ExchangeServerProgram.convertObjectToByteArr(exchangeRequest);
            if(null != buf)
            {
                packet = new DatagramPacket(buf, buf.length, hostAddress , port);
                socket.send(packet);
                return true;
            }
            else
                JOptionPane.showMessageDialog(null, "Sorry, this exchange cannot be trasnmitted to server");

        } catch (IOException e){e.printStackTrace();}

        return false;
    }


}  

服务器

public class ExchangeServerProgram extends Thread
{
    public static final int DEFAULT_SERVER_PORT = 4444;
    public static final int DEFAULT_BUFFER_SIZE = 1024;
    private DatagramSocket socket;
    private DatagramPacket packet;
    private boolean listening = false;// default initial value
    private byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];

    public ExchangeServerProgram() throws SocketException
    {
        socket = new DatagramSocket(DEFAULT_SERVER_PORT);
        packet = new DatagramPacket(buffer , buffer.length);
    }

    public void run()
    {
        listening = true;
        while(listening)
        {
            try
            {
                socket.receive(packet);
                packet.getAddress(); // this line BEFORE the thread starts works fine.
                new ExchangeClientRequestHandlerThread(packet ).start(); // inside this thread the trouble starts 
                                                                        // when using the SAME line from above

            } catch (IOException e){e.printStackTrace();}

        }

    }

    public static byte [] convertObjectToByteArr(Object obj)
    {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte [] buffer = null;
        ObjectOutput out = null;
        try {
          out = new ObjectOutputStream(bos);   
          out.writeObject(obj);
          out.flush();
          buffer = bos.toByteArray();
        } 
        catch (IOException e){e.printStackTrace(); } 
        finally {
            try
            {
                bos.close();
            } catch (IOException e){e.printStackTrace(); }
        }

        return buffer;
    }
}  

线程处理数据包,这就是我陷入困境的地方

public class ExchangeClientRequestHandlerThread extends Thread
{
    private DatagramPacket packet;
    public ExchangeClientRequestHandlerThread(DatagramPacket packet)
    {
        this.packet = packet;
    }

    public void run()
    {
        if(null == packet)
            return;
        packet.getAddress(); //... get stuck here

        System.out.println("doesn't get to this code line");
    }

}    

交换请求

public class ExchangeRequest implements Serializable
{
    private static final long serialVersionUID = -1355753051547829379L;
    private String coinFrom;
    private String coinTo;
    private double amount;
    private int requestId;

    public ExchangeRequest(String coinFrom, String coinTo, double amount , int requestId)
    {
        this.coinFrom = coinFrom;
        this.coinTo = coinTo;
        this.amount = amount;
        this.requestId = requestId;
    }
    //getters & setters

}  

主要

public class Main
{
    public static void main(String [] args)
    {
        try
        {
            ExchangeServerProgram server = new ExchangeServerProgram();
            server.start(); // starts the server

            String inputIpAddress = "localhost";
            ExchangeClientProgram clientProgram = new ExchangeClientProgram(inputIpAddress, ExchangeServerProgram.DEFAULT_SERVER_PORT);
            ExchangeRequest request = new ExchangeRequest("usd", "euro", 4, 1111); // 1111 is just an ID number for the message
            clientProgram.sendRequestPacket(request);

            while(true)
            {
                // this while loop is just for the example  
                // here I am waiting for received packet  
                // via "socket.receive();"
            }
        } catch (SocketException | UnknownHostException e)
        {
            e.printStackTrace();
        }

    }
}

最佳答案

线程是你的问题。您有一个线程调用 receive(packet),当您收到它时,您将其传递给另一个线程进行处理,从而使第一个线程再次调用 receive(packet)

问题在于 receivepacket 上同步,并且 DatagramPacket 中的方法也是同步的,因此当第一个线程在 上被阻塞时receive(packet) 如果不阻塞线程,则无法调用任何 DatagramPacket 方法。

可能的解决方案包括在原始线程中处理数据包或为每个 receive() 创建一个新的 DatagramPacket

关于java - 为什么 DatagramPacket 对象在使用其方法之一时会卡住?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48388532/

相关文章:

java - 针对蜂窝调制解调器项目的客户端/服务器交互故障排除的建议和帮助

java - 在 Eclipse 中尝试 "Import Plug-ins and Fragments"时没有源文件

java - 如何从 cassandra 中的行获取文本集

java - 传入消息的监听器

java - 如何设置Vaadin 6 'Select'框选择值

java - 空白弹出菜单和组合框

c++ - 在新线程中创建对话框

java - 如何使用Java多线程检索mysql数据

node.js - socket.io 连接在生产环境中失败,在 localhost 中工作

linux - 如何知道nc使用的源ip地址连接到目的地