当前位置: 首页 > 知识库问答 >
问题:

使用TCP over socket从服务器端向客户端发送ArrayList

温嘉赐
2023-03-14

我试图将一个对象从服务器端发送到客户端,但找不到问题。以下是我在客户端遇到的错误:

java.io.StreamCorruptedException: invalid type code: 43
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at connection.MainClient.doAll(MainClient.java:56)
at connection.TestScreen$2.actionPerformed(TestScreen.java:82)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

下面是服务器端方法:无限循环中的separate方法只是从文件中读取,并将用户名和密码解析为ArrayList,这是服务器类中的实例变量。

    public void doStuff() throws Exception
{
    ServerSocket serverSocket = new ServerSocket(5001);
    Socket clientSocket = serverSocket.accept();
    PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
    BufferedReader in = new BufferedReader(
            new InputStreamReader(
            clientSocket.getInputStream()));
    ObjectOutputStream objectOutput = new ObjectOutputStream(clientSocket.getOutputStream());
    String inputLine;
    out.println("Connected");
    while(true)
    {
        seperate();
        while ((inputLine = in.readLine()) != null) 
        {
            if(inputLine.equalsIgnoreCase("users"))
                objectOutput.writeObject(getUserNames());
            else
                if(inputLine.equalsIgnoreCase("pass"))
                    objectOutput.writeObject(getPassWords());
                else
                    if(inputLine.equalsIgnoreCase("stop"))
                        objectOutput.reset();
        }
    }
}

以下是从服务器请求信息的客户端:

public boolean doAll(String name, String pass) throws Exception
{
    try 
    {
        kkSocket = new Socket("PC", 5001);
        out = new PrintWriter(kkSocket.getOutputStream(), true);
        in = new BufferedReader(new InputStreamReader(kkSocket.getInputStream()));
    } 
    catch (UnknownHostException e) 
    {
        System.err.println("Don't know about host: PC.");
        System.exit(1);
    }
    catch (IOException e) 
    {
        System.err.println("Couldn't get I/O for the connection to: PC.");
        System.exit(1);
    }

    ObjectInputStream objectInput = new ObjectInputStream(kkSocket.getInputStream());

    out.println("user");
    Object obj = objectInput.readObject();
    users = (ArrayList<String>)obj;
    out.println("pass");
    obj = objectInput.readObject();
    this.pass = (ArrayList<String>)obj;
    out.println("stop");
    objectInput.close();
    out.close();
    in.close();
    kkSocket.close();

    if(userIsRegistered(name,pass))
        return true;
    return false;
}

我对学习服务器套接字和套接字还不熟悉,但我在这里试图实现的是以下目标。当我在另一节课上按下按钮时,我会这样做:

MainClient b = new MainClient();
login = b.doAll(userField.getText(),passField.getText());
Login is obviously a boolean.

几乎是一个通过服务器到cleint的登录系统,当按下登录按钮时,它会调用一个客户端连接到该服务器,获取用户列表,并在服务器上传递,该服务器存储在指定目录中的文本文件中。然后,当客户端接收到这些信息时,它会从我从两个文本字段中获取的字符串中检查它是否可能是用户,并返回true或false。然后关闭服务器的套接字,每次都应该重新连接,对吗?

我的主要问题是如何修复它不断抛出的错误?

共有2个答案

唐兴发
2023-03-14

不能对字节输入流使用InputStreamReader。它需要输入流中的字符/字符串。请尝试ObjectInputStream。

提示一下:输入流类型应该在服务器端和客户端都匹配。你不能把它们混在一起。在服务器上使用的是ObjectOutputStream,因此相应的ObjectInputStream应该在客户端上使用。

赫连晋
2023-03-14

您的代码流程如下所示:

  1. 服务器已启动,正在等待与客户端的连接
  2. 服务器使用serverSocket从客户端接受连接。accept()
  3. 服务器通过out使用PrintWriter对象向客户端发送String消息(“已连接”)。println(“已连接”)
  4. 客户端正在使用ObjectInputStream对象读取该消息,这导致流不匹配,因此违反了内部一致性检查。这就是为什么在客户端抛出StreamCorruptedException。因此,与其使用ObjectInputStream读取服务器发送的普通消息,不如使用上面创建的BufferedReader对象

因此,在客户端,您的代码应该修改为:

ObjectInputStream objectInput = new ObjectInputStream(kkSocket.getInputStream());
String message = in.readLine();//use BufferedReader to read the plain message coming from Server.
System.out.println("Message from server: "+message);
out.println("user");
Object obj = objectInput.readObject();
 类似资料:
  • 我正在创建我的产品,并与这个问题。有一天,我设置了Socket.io,一切都很好。第二天,我将服务器和客户端从http迁移到HTTPS。迁移后客户端和服务器端仍然连接,但不能从客户端发射到服务器,从服务器发射到客户端。 我的ssl证书位于和中,它们加载正确。运行在上的服务器 我的示例react组件。我的react应用程序运行在上。HTTPS连接良好,工作良好。 我该怎么办?也许我在中错误地使用了s

  • 问题内容: 我将实现类似于Facebook通知和此网站的内容(StackOverflow的通知会通知我们是否有人为我们的问题写评论/答案等)。请注意,用户将使用我的应用程序作为网站而不是移动应用程序。 我遇到以下获取结果的答案,但我需要推送结果而不是获取结果。 根据建议,我在实体类中创建了一个简单方法,并向其中添加了@PostPersist,但此方法不起作用,因此基于此答案,我添加了persist

  • 问题内容: 所以现在,我正在制作一个基于客户端服务器应用程序的多线程。在服务器端,我为接受的每个连接创建了一个线程。 在线程类中,我创建了一种将命令发送到客户端的方法。我只想要的是如何将参数发送到所有正在运行的客户端?为简单起见,我只想使此服务器向所有连接的客户端发送消息。 我已经阅读了这篇文章,并从此链接中找到方法。但是,当我尝试使用自己的代码时,中没有类似的方法。 好的,这是我的服务器和线程示

  • 我正在编写一个程序,将数据从服务器连续发送到客户端。在这里,我使用示例的时间戳将其发送给连接的多个客户端。我使用多线程来支持多个客户端。我希望每10秒向客户端发送一次时间。但在我的代码中,客户端在收到第一个数据后停止。如何让客户端连续接收数据。我尝试在客户端添加while循环,但这并不可行。有什么建议吗 以下是示例代码:服务器端: 客户端: 我的输出: 客户端所需输出:

  • 我有一个基本的Netty服务器(来自教程)(http://netty.io/wiki/user-guide-for-4.x.html),它会接收来自客户端的请求,但如何向客户端发送字符串呢? 例如,在普通的Minecraft服务器上,您在配置文件中指定“MOTD”,当客户端从服务器列表中发出信号时,它将显示该字符串。我需要做同样的事情,但是从我的服务器代码中。