![](/img/trans.png)
[英]NoClassDefFoundException when receiving object with readObject()
[英]The readObject() Method of objectOutputStream is not receiving the object written on the inputStream to the Client?
目的是将坐标从一个客户端(正在绘制)传输到连接到服务器的所有客户端,然后在它们各自的面板上绘制,但客户端中的 readObject() 似乎永远不会获取数据。 输入正确执行 go 到服务器,但从服务器,其他客户端无法收听。
当使用 BufferedStream 或 DataInput/OutputStream any Other 时,输入似乎滞后或行为不端。 所以更喜欢ObjectOutputStream。 程序快照。
客户端在后台线程listenData 中侦听输入。
客户代码 -
公共 class 客户扩展 JFrame {
private static final long serialVersionUID = 1L;
private Coordinates crdntsToSend;
private Coordinates crdntsReceived;
private JPanel contentPane;
private Socket socket;
private ObjectOutputStream toServerPipe;
private ObjectInputStream fromServerPipe;
private JPanel paintPanel;
public Clients(String name,int port,String ip) {
setResizable(false);
setTitle("Skribbl");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(600,550);
createConnection(ip,port);
listen();
}
private void createConnection(String ip,int port)
{
try {
socket = new Socket(ip,port);
toServerPipe = new ObjectOutputStream(socket.getOutputStream());
fromServerPipe = new ObjectInputStream(socket.getInputStream());
toServerPipe.flush();
userInterfaceSetter();
} catch (IOException e) {
System.out.println("Port Not Found!!!");
return;
}
}
private void userInterfaceSetter()
{
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e1) {
e1.printStackTrace();
}
getContentPane().setLayout(null);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
GridBagLayout gbl_contentPane = new GridBagLayout();
gbl_contentPane.columnWidths = new int[] {0, 0};
gbl_contentPane.rowHeights = new int[]{0, 0, 0};
gbl_contentPane.columnWeights = new double[]{1.0, Double.MIN_VALUE};
gbl_contentPane.rowWeights = new double[]{1.0, 0.0, Double.MIN_VALUE};
contentPane.setLayout(gbl_contentPane);
paintPanel = new JPanel();
paintPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
drawOnPanel(e.getX(),e.getY());
}
});
paintPanel.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
drawOnPanel(e.getX(),e.getY());
}
});
paintPanel.setBackground(new Color(175, 238, 238));
GridBagConstraints gbcPaintPanel = new GridBagConstraints();
gbcPaintPanel.insets = new Insets(10, 10, 10, 10);
gbcPaintPanel.fill = GridBagConstraints.BOTH;
gbcPaintPanel.gridx = 0;
gbcPaintPanel.gridy = 0;
contentPane.add(paintPanel, gbcPaintPanel);
JLabel lblScore = new JLabel("Score: ");
GridBagConstraints gbclblScore = new GridBagConstraints();
gbclblScore.insets = new Insets(0, 0, 10, 0);
gbclblScore.anchor = GridBagConstraints.WEST;
gbclblScore.gridx = 0;
gbclblScore.gridy = 1;
contentPane.add(lblScore, gbclblScore);
}
private void drawOnPanel(int x,int y)
{
Graphics g = paintPanel.getGraphics();
g.fillOval(x, y, 7, 7);
sendData(x,y);
}
private void sendData(int x, int y) {
try {
crdntsToSend = new Coordinates(x,y);
toServerPipe.writeObject(crdntsToSend);
toServerPipe.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
private void listen()
{
SwingWorker<Void, String> listenData = new SwingWorker<Void, String>() {
boolean go = true;
String[] receivedData;
String str;
@Override
protected Void doInBackground() throws Exception {
while(go)
{
crdntsReceived = (Coordinates) fromServerPipe.readObject();
str= crdntsReceived.toString();
publish(str);
}
return null;
}
@Override
protected void process(List<String> chunks) {
receivedData = str.split(" ");
drawOnPanel(Integer.parseInt(receivedData[0]),Integer.parseInt(receivedData[1]));
}
};
listenData.execute();
}
}
ServerHandler 代码(服务器线程) -
package theskribbl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class HandleClient implements Runnable
{
private Socket[] socket;
private ObjectInputStream fromClients;
private ObjectOutputStream toClients;
private static int count = 0;
private int temp;
public HandleClient(Socket[] socket, int count)
{
HandleClient.count = count;
temp=count;
this.socket=socket;
try
{
fromClients = new ObjectInputStream(socket[count].getInputStream());
toClients = new ObjectOutputStream(socket[count].getOutputStream());
toClients.flush();
}
catch (IOException e)
{
e.printStackTrace();
}
}
@Override
public void run()
{
int i;
Coordinates coordinate;
while(true)
{
i=0;
try
{
coordinate = (Coordinates) fromClients.readObject();
System.out.println(coordinate.toString());
while(i<=count)
{
if(i!=temp)
{
toClients = new ObjectOutputStream(socket[i].getOutputStream());
toClients.writeObject(coordinate);
toClients.flush();
}
i++;
}
}
catch (Exception e)
{
System.out.println("Something Went Wrong");
return;
}
}
}
}
客户代码 - https://repl.it/@GirirajSingh/skribbl#Clients.java
登录客户端的代码 - https://repl.it/@GirirajSingh/skribbl#Login.java
处理客户端(服务器端)的代码 - https://repl.it/@GirirajSingh/skribbl#HandleClient.java
服务器代码 - https://repl.it/@GirirajSingh/skribbl#ServerClass.java
ObjectOutputStream
和ObjectInputStream
构造函数调用必须匹配 - 创建ObjectOutputStream
时,它会发送 header ,创建ObjectInputStream
时必须接收该 header 。
我没有时间研究代码,但看起来 output 流在每次服务器发送某些内容时都在循环中构建。 客户每次收到坐标时是否都会重新打开输入?
查看ObjectOutputStream
和ObjectInputStream
的文档以获得更好的解释。 最好从一个(非常)简单的原型开始:一台服务器,一个客户端,并且只发送几个(测试 = 固定)坐标。
doInBackGround()
(在SwingWorker
内部)可能抛出了一个异常! 建议在SwingWorker
终止后(在其覆盖的done()
内)调用get()
方法来检查这一点 - 如果计算抛出异常,这将抛出ExecutionException
,其中将包含有关异常的信息。
在SwingWorker
中添加如下代码:
@Override
protected void done() {
try {
get();
} catch (Exception ex) {
ex.printStackTrace();
}
}
注意:此代码不是为了解决问题,只是为了显示可能的错误
您所说的标头不匹配,实际上它们是匹配的,因为它们是通过同一个套接字初始化的。 使用 DataOutputStream/DataInputStream(write()/read() ) 进行相同的过程,但是在此过程中,数据会泄漏,因为如果鼠标快速拖动,则数据会在两者之间丢失。 所以这就是为什么我想使用 ObjectOutputStream 的 read/writeObject()。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.