[英]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線程上運行)中引用了一堆字段。 ( playerx
, playery
, left
, right
, up
, down
)同步在這里並不是真正的問題。 但是,JVM沒有義務(盡管可以,但可以)將其他線程所做的更改通知線程。 自己完成此操作后,我發現有時線程會立即看到更改,有時會出現明顯的滯后(導致令人討厭的跳躍圖形),有時甚至永遠不會看到更改。
語言規范要求在一個線程啟動時,在完成連接時,在另一個線程離開同一對象上同步的塊之后再進入另一個塊之后,當一個易失字段被讀寫時,在一個線程進入同步塊時在線程之間傳輸數據。 ,並調用Atomic方法。
因此,您要做的是手動遍歷Client類中的所有字段,並確保將每個字段標記為final
, volatile
或僅在synchronized
塊中引用或僅在一個線程上引用(如Swing方法) 。 您要做的最快的事情就是使這些字段易變。 同步塊可能更有效。 我相信,進入和退出它們的成本比對volatile的讀取和寫入要高,但是一旦您進入,就可以以很少的額外成本修改一堆字段。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.