簡體   English   中英

客戶端不起作用-服務器

[英]Does not work client - 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;
            }
        }

    }
}

客戶

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

當我運行代碼(運行多個窗口進行檢查)時,即使圓應該移動了,它也不起作用..

請幫助解決它)

先感謝您!

這是相當復雜的東西。 我可以看到兩個問題。

較小的問題(我認為):Swing類和方法必須在事件隊列上運行,只有很少的例外(例如Component / JComponent中的repaint()方法)。 在您的Client中,在啟動線程上運行的main()方法創建一個JFrame並調用多個方法。 每個人都這樣做,我認為每個人都可以擺脫它,但這很危險。 使用EventQueue.InvokeLater將代碼放到UI線程上。 我檢查了您的run()方法,但它們似乎沒有碰到Swing(除了對repaint()的合法調用以外),但請注意它們。 從那里調用Swing方法,您會遇到更大的問題。

主要問題:在客戶端運行方法某些按鈕代碼(在UI線程上運行)中引用了一堆字段。 playerxplayeryleftrightupdown )同步在這里並不是真正的問題。 但是,JVM沒有義務(盡管可以,但可以)將其他線程所做的更改通知線程。 自己完成此操作后,我發現有時線程會立即看到更改,有時會出現明顯的滯后(導致令人討厭的跳躍圖形),有時甚至永遠不會看到更改。

語言規范要求在一個線程啟動時,在完成連接時,在另一個線程離開同一對象上同步的塊之后再進入另一個塊之后,當一個易失字段被讀寫時,在一個線程進入同步塊時在線程之間傳輸數據。 ,並調用Atomic方法。

因此,您要做的是手動遍歷Client類中的所有字段,並確保將每個字段標記為finalvolatile 僅在synchronized塊中引用僅在一個線程上引用(如Swing方法) 。 您要做的最快的事情就是使這些字段易變。 同步塊可能更有效。 我相信,進入和退出它們的成本比對volatile的讀取和寫入要高,但是一旦您進入,就可以以很少的額外成本修改一堆字段。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM