简体   繁体   English

客户端不起作用-服务器

[英]Does not work client - server

There is a problem, the following code does not work code: 有问题,以下代码不起作用:

Server 服务器

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    static ServerSocket serverSocket;
    static Socket socket;
    static DataOutputStream out;
    static DataInputStream in;
    static Users[] user = new Users[10];

    public static void main(String[] args) {
        try {
            System.out.println("Server Started...");
            serverSocket = new ServerSocket(7778);
            System.out.println("Server Start.");
            while (true) {
                socket = serverSocket.accept();
                for (int i = 0; i < 10; i++) {
                    if (user[i] == null) {
                        System.out.println("Conection from"
                                + socket.getInetAddress());
                        out = new DataOutputStream(socket.getOutputStream());
                        in = new DataInputStream(socket.getInputStream());

                        user[i] = new Users(out, in, user, i);
                        Thread thread = new Thread(user[i]);
                        thread.start();
                        break;
                    }
                }
            }

        } catch (IOException e) {

        }
    }
}

class Users implements Runnable {

    DataOutputStream out;
    DataInputStream in;
    Users[] user = new Users[10];
    String name;
    int playerid;
    int playeridln;
    int xin;
    int yin;

    public Users(DataOutputStream out, DataInputStream in, Users[] user, int pid) {
        this.out = out;
        this.in = in;
        this.user = user;
        this.playerid = pid;
    }

    public void run() {
        try {
            out.writeInt(playerid);
        } catch (IOException e1) {
            System.out.println("Failed to send PlayerID");
        }
        while (true) {
            try {
                playeridln = in.readInt();
                xin = in.readInt();
                yin = in.readInt();

                for (int i = 0; i < 10; i++) {
                    if (user[i] != null) {
                        user[i].out.writeInt(playeridln);
                        user[i].out.writeInt(xin);
                        user[i].out.writeInt(yin);
                    }
                }
            } catch (IOException e) {
                user[playerid] = null;
                break;
            }
        }

    }
}

Client 客户

import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Client extends JPanel implements Runnable, KeyListener {

    private static final long serialVersionUID = 1L;
    static Socket socket;
    static DataInputStream in;
    static DataOutputStream out;

    int playerid;

    int[] x = new int[10];
    int[] y = new int[10];

    boolean left, up, right, down;

    int playerx;
    int playery;

    public Client() {
        init();
    }

    public void init() {
        try {
            System.out.println("Conecting to serever...");
            socket = new Socket("localhost", 7778);
            System.out.println("Connection successful");
            in = new DataInputStream(socket.getInputStream());
            playerid = in.readInt();
            out = new DataOutputStream(socket.getOutputStream());
            Input input = new Input(in, this);
            Thread thread = new Thread(input);
            thread.start();
            Thread thread2 = new Thread(this);
            thread2.start();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void updateCoordinates(int pid, int x2, int y2) {
        this.x[pid] = x2;
        this.y[pid] = y2;
    }

    public void paint(Graphics g) {
        repaint();
        for (int i = 0; i < 10; i++) {
            g.drawOval(x[i], y[i], 5, 5);
        }
    }

    public void run() {
        while (true) {
            if (right) {
                playerx += 10;
            }
            if (left) {
                playerx -= 10;
            }
            if (down) {
                playery += 10;
            }
            if (up) {
                playery -= 10;
            }
            if (right || left || up || down) {
                try {
                    out.writeInt(playerid);
                    out.writeInt(playerx);
                    out.writeInt(playery);
                } catch (Exception e) {
                    System.out.println("Erro Coordinates");
                }
            }
            repaint();
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == 37) {
            left = true;
        }
        if (e.getKeyCode() == 38) {
            up = true;
        }
        if (e.getKeyCode() == 39) {
            right = true;
        }
        if (e.getKeyCode() == 40) {
            down = true;
        }
    }

    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == 37) {
            left = false;
        }
        if (e.getKeyCode() == 38) {
            up = false;
        }
        if (e.getKeyCode() == 39) {
            right = false;
        }
        if (e.getKeyCode() == 40) {
            down = false;
        }
    }

    public void keyTyped(KeyEvent e) {
    }

    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setSize(300, 300);
        f.getContentPane().add(new Client());
        f.setVisible(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

class Input implements Runnable {

    DataInputStream in;
    Client client;

    public Input(DataInputStream in, Client c) {
        this.in = in;
        this.client = c;
    }

    public void run() {
        while (true) {
            try {
                int playerd = in.readInt();
                int x = in.readInt();
                int y = in.readInt();
                client.updateCoordinates(playerd, x, y);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

When I run the code (run multiple windows to check) It does not work, even though the circle should move .. 当我运行代码(运行多个窗口进行检查)时,即使圆应该移动了,它也不起作用..

Help to solve it, please) 请帮助解决它)

Thank you in advance! 先感谢您!

This is rather complicated stuff. 这是相当复杂的东西。 There's two problems I can see. 我可以看到两个问题。

Minor problem (I think): Swing classes and methods, with very few exceptions (such as the repaint() method in Component/JComponent) must run on the event queue. 较小的问题(我认为):Swing类和方法必须在事件队列上运行,只有很少的例外(例如Component / JComponent中的repaint()方法)。 In your Client the main() method, which runs on the startup thread, creates a JFrame and calls several methods. 在您的Client中,在启动线程上运行的main()方法创建一个JFrame并调用多个方法。 Everybody does this, and I think everybody gets away with it, but it's dangerous. 每个人都这样做,我认为每个人都可以摆脱它,但这很危险。 Use EventQueue.InvokeLater to put the code onto the UI thread. 使用EventQueue.InvokeLater将代码放到UI线程上。 I checked your run() methods, but they don't seem to touch Swing, (other than a legit call to repaint()) but keep an eye on them. 我检查了您的run()方法,但它们似乎没有碰到Swing(除了对repaint()的合法调用以外),但请注意它们。 Call a Swing method from there and you'll have a bigger problem. 从那里调用Swing方法,您会遇到更大的问题。

Major problem: You have a bunch of fields referenced in the Client run method and in some button code (running on the UI thread). 主要问题:在客户端运行方法某些按钮代码(在UI线程上运行)中引用了一堆字段。 ( playerx , playery , left , right , up , down ) Synchronization is not really a problem here. playerxplayeryleftrightupdown )同步在这里并不是真正的问题。 However, the JVM is under no obligation (though it can if it wants) to inform a thread of changes made by other threads. 但是,JVM没有义务(尽管可以,但可以)将其他线程所做的更改通知线程。 Having done this myself, I've found that sometimes the threads see changes immediately, sometimes after a noticable lag (leading to annoying, jumpy graphics), and sometimes never. 自己完成此操作后,我发现有时线程会立即看到更改,有时会出现明显的滞后(导致令人讨厌的跳跃图形),有时甚至永远不会看到更改。

The language spec requires that data be transferred between threads when a thread starts, when it finishes with a join, when a thread enters a synch block after another thread has left a block synched on the same object, when a volatile field is written and read, and after calls to Atomic methods. 语言规范要求在一个线程启动时,在完成连接时,在另一个线程离开同一对象上同步的块之后再进入另一个块之后,当一个易失字段被读写时,在一个线程进入同步块时在线程之间传输数据。 ,并调用Atomic方法。

So what you want to do is go through, manually, all the fields in your Client class and for each one make sure it is marked as final , volatile , or referenced only in synchronized blocks or only referenced on one thread (like Swing methods). 因此,您要做的是手动遍历Client类中的所有字段,并确保将每个字段标记为finalvolatile 仅在synchronized块中引用仅在一个线程上引用(如Swing方法) 。 The quickest thing for you to do would be make those fields volatile. 您要做的最快的事情就是使这些字段易变。 Synch blocks might be more efficient. 同步块可能更有效。 I believe that they cost more to get into and out of than reads and writes to volatiles, but once in you can modify a bunch of fields at little extra cost. 我相信,进入和退出它们的成本比对volatile的读取和写入要高,但是一旦您进入,就可以以很少的额外成本修改一堆字段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM