Почему моя простая сетевая программа не работает?

Поэтому я изучаю сеть UDP, используя руководства в Интернете. Я нашел руководство, в основном копировал/вставлял код, и это сработало. Тогда я, очевидно, хотел расшириться самостоятельно. Я пытаюсь сделать простую вещь, которая даст серверу положение мыши клиента, а затем сервер отправит обратно одно и то же сообщение всем шапкам. Но по какой-то причине он отлично работает от 0 до 100 раз, а затем просто останавливается. Вот мой код:

Сервер:

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

Может быть, это потому, что он не синхронизирован правильно, и сервер отправляет сообщение до того, как клиент доберется до части кода, где он проверяет сообщение? Я понятия не имею, потому что я действительно новичок в этом. Я хотел бы узнать, почему это происходит и как это исправить! Извините за беспорядочный код, я новичок в этом и кодировании в целом.


person Miles    schedule 12.07.2015    source источник


Ответы (1)


Скорее всего, вы сталкиваетесь с проблемами синхронизации из-за того, что вы продолжаете открывать и закрывать сокет сервера. Это создает условие гонки между send() клиента и сервером. Создание DatagramSocket. Если клиент отправляет свой пакет до того, как сокет сервера будет инициализирован, сервер не получит его, а просто будет ждать его вечно. Это известно как взаимоблокировка.

Чтобы избежать этой проблемы, просто держите сокет сервера открытым. Открывать его при инициализации объекта Сервер и закрывать при завершении работы серверной программы. Таким образом, дейтаграммы, отправленные клиентом, будут храниться в буфере сокета до тех пор, пока сервер не вызовет receive().

С другой стороны, конструктор сервера и метод run() имеют много повторяющегося кода. Дублирование кода часто приводит к несоответствиям в логике программы и, следовательно, к ошибкам. Старайтесь избегать копирования кода.

person Malt    schedule 12.07.2015