[英]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.