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

时间:2015-07-12 09:10:25

标签: java network-programming udp java-io

所以我正在使用互联网上的指南学习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());
    }
}

也许是因为它没有正确同步,服务器在客户端到达检查消息的代码部分之前发送消息?我不知道,因为我对此真的很陌生。我很想知道为什么会这样,以及如何解决它!对不起凌乱的代码,我是新手,并且编码一般。

1 个答案:

答案 0 :(得分:0)

由于您不断打开和关闭服务器套接字,您很可能会遇到同步问题。这会在客户端的 send()和服务器的DatagramSocket创建之间创建race condition。如果客户端在服务器套接字初始化之前发送其数据包,则服务器不会收到它,只是等待它永远。这称为deadlock

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

另外,服务器的构造函数和 run()方法有很多重复的代码。代码重复经常导致程序逻辑的不一致,因此也会导致错误。尽量避免复制粘贴代码。