为什么我的简单网络程序坏了?

Why is my simple networking program breaking?

所以我正在使用 Internet 上的指南学习 UDP 网络。我找到了一个指南,主要是 copy/pasted 代码,它起作用了。所以后来我显然想自己扩展。我正在尝试做一个简单的事情,它将为服务器提供客户端鼠标位置,然后服务器将向所有大写字母发送完全相同的消息。但出于某种原因,它在 0-100ish 次的任何地方都能完美运行,然后就停止了。这是我的代码:

服务器:

public class Server implements Runnable {

    boolean running = false;
    long time;
    InetAddress IPAddress;
    int port;

    public static void main(String[] args) throws Exception {
        Thread th = new Thread(new Server());
        th.start();
    }

    public Server() throws Exception {
        DatagramSocket serverSocket = new DatagramSocket(9876);
        byte[] receiveData = new byte[1024];
        byte[] sendData = new byte[1024];

        System.out.println("Server started");
        DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
        serverSocket.receive(receivePacket);
        IPAddress = receivePacket.getAddress();
        port = receivePacket.getPort();

        System.out.println("Client connected at " + IPAddress);
        String send = "Connected!";
        sendData = send.getBytes();

        DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port);
        serverSocket.send(sendPacket);
        serverSocket.close();

        time = System.nanoTime();
        running = true;
    }

    public void run() {     
        int x = 0;
        while(running) {
            if(System.nanoTime() > time + 60/(1e9)) {
                time = System.nanoTime();
                try { 
                    x++;
                    DatagramSocket serverSocket = new DatagramSocket(9876);
                    byte[] receiveData = new byte[1024];
                    byte[] sendData = new byte[1024];

                    DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                    serverSocket.receive(receivePacket);
                    System.out.println("Received message");

                    IPAddress = receivePacket.getAddress();
                    port = receivePacket.getPort();

                    String sentence = new String(receivePacket.getData());
                    System.out.println("RECEIVED " + sentence);

                    String capSentence = sentence.toUpperCase();
                    sendData = capSentence.getBytes();

                    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port);
                    serverSocket.send(sendPacket);
                    System.out.println("Sent message.");
                    System.out.println(x);
                    serverSocket.close();   
                } catch(Exception e) {
                    System.out.println(e.getMessage());
                }
            }
        }
    }
}

客户:

public class Client implements Runnable {

    boolean foundConnection = false;
    boolean running = false;        
    long time;

    public static void main(String[] args) throws Exception {
        Thread th = new Thread(new Client());
        th.start();
    }

    public Client() throws Exception {
        time = System.nanoTime();
        running = true;
    }

    public void run() {
        while(running) {
            if(System.nanoTime() > time + (60/1e9)) {
                time = System.nanoTime();

                try {
                    DatagramSocket clientSocket = new DatagramSocket();
                    InetAddress IPAddress = InetAddress.getByName("localhost");

                    byte[] sendData = new byte[1024];
                    byte[] receiveData = new byte[1024];

                    String send = "Mouse is at " + mouse();
                    sendData = send.getBytes();

                    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9876);
                    clientSocket.send(sendPacket);
                    System.out.println("Sent message.");

                    DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                    clientSocket.receive(receivePacket);
                    System.out.println("Received message.");

                    String modSentence = new String(receivePacket.getData());
                    System.out.println("FROM SERVER: " + modSentence);
                    clientSocket.close();
                } catch(Exception e) {
                    System.out.println("Error"); 
                }
            }
        }
    }

    public static Point mouse() {
        return new Point((int)MouseInfo.getPointerInfo().getLocation().getX(), 
                (int)MouseInfo.getPointerInfo().getLocation().getY());
    }
}

可能是因为它没有正确同步,服务器在客户端到达检查消息的代码部分之前发送消息?我不知道,因为我对此很陌生。我很想知道为什么会发生这种情况以及如何解决它!抱歉,代码乱七八糟,我是新手,一般来说是编码。

您很可能 运行 由于不断打开和关闭服务器套接字而陷入同步问题。这会创建一个 race condition between the client's send() and the server's DatagramSocket creation. If the client sends its packet before the server's socket is initialized, the server won't receive it, and just wait for it forever. This is known as a deadlock.

要避免此问题,请保持服务器的套接字打开。在Server对象初始化时打开,在服务器程序结束时关闭。这样,客户端发送的数据报将保存在套接字缓冲区中,直到服务器调用 receive().

换句话说,Server 的构造函数和 运行() 方法有很多重复代码。代码重复经常导致程序逻辑不一致,从而导致错误。尽量避免复制粘贴代码。