通过套接字发送对象

3
我正在尝试通过Java Socket发送自定义对象。我知道需要将包含我想要发送的对象的类放在同一个包中,具有相同的serialVersionUID并实现Serializable接口。我已经这样做了,但仍然无法通过Socket发送对象。我哪里做错了?以下是客户端代码:
客户端中的用户类
package data;
import java.io.Serializable;

public class User implements Serializable {

    /**
     * 
     */
    public static final long serialVersionUID = 1L;
    private String username = null;
    private String hashedPassword = null;
    private Integer code = null;
    private String from = null;
    private String to = null;
    private Object data = null;

    public User() {

    }

    public User(Integer code) {
        this.code = code;
    }

    public User(Integer code, Object data) {
        this.code = code;
        this.data = data;
    }

    public User(String username, String hashedPassword, Integer code, String from, String to, Object data) {
        this.username = username;
        this.hashedPassword = hashedPassword;
        this.code = code;
        this.from = from;
        this.to = to;
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }
    // other getters and setters
}

发送用户类对象的代码:

package tankclient;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import data.*;

public class Main {
    public static void main(String args[]) {
        Socket socket = null;
        ObjectOutputStream oos = null;
        ObjectInputStream ois = null;
        boolean isConnected = false;
        String ipServer = "localhost";
        int portServer = 4444;
        try {
            // Print("connecting to server...");
            socket = new Socket(ipServer, portServer);
            isConnected = true;
            oos = new ObjectOutputStream(socket.getOutputStream());
            ois = new ObjectInputStream(socket.getInputStream());
            oos.writeObject(new User());
            // Print("connect server success");
        } catch (Exception ex) {
            isConnected = false;
            ex.printStackTrace();
        }
        // DataTransfer transfer = new DataTransfer();
        // //transfer.SendDataRequest(new DataRequest(3));
        // transfer.TestSend();
    }
}

这是服务器的代码:
用户类的代码:与客户端的用户完全相同(我从客户端复制并粘贴到服务器中)
服务器接收用户对象的代码:

package tankserver;

import data.*;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Main {

    public static void main(String args[]) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        ObjectOutputStream oos = null;
        ObjectInputStream ois = null;
        boolean isConnected = false;
        int portServer = 4444;
        try {
            System.out.println("waiting for client to connect ...");
            serverSocket = new ServerSocket(portServer);
            socket = serverSocket.accept();
            oos = new ObjectOutputStream(socket.getOutputStream());
            ois = new ObjectInputStream(socket.getInputStream());
            isConnected = true;
            System.out.println("connected");
            User obj = (User) ois.readObject();
            System.out.println(obj.toString());
        } catch (Exception ex) {
            isConnected = false;
            ex.printStackTrace();
        }
        //DataTransfer transfer = new DataTransfer();

        //transfer.GetDataRequest();
        //transfer.TestRecieve();
    }

}

以下是我收到的堆栈跟踪(在服务器端):

java.net.SocketException: 连接重置 at java.net.SocketInputStream.read(SocketInputStream.java:209) at java.net.SocketInputStream.read(SocketInputStream.java:141) at java.net.SocketInputStream.read(SocketInputStream.java:223) at java.io.ObjectInputStream$PeekInputStream.peek(ObjectInputStream.java:2296) at java.io.ObjectInputStream$BlockDataInputStream.readBlockHeader(ObjectInputStream.java:2476) at java.io.ObjectInputStream$BlockDataInputStream.refill(ObjectInputStream.java:2546) at java.io.ObjectInputStream$BlockDataInputStream.skipBlockData(ObjectInputStream.java:2448) at java.io.ObjectInputStream.skipCustomData(ObjectInputStream.java:1944) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1621) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) at tankserver.Main.main(Main.java:31) 构建成功(总时间:8秒)

当我尝试调试时,会出现以下情况:当我在客户端中设置断点(服务器正常运行)并逐步运行时,它可以正常工作,但当我在服务器中设置断点(客户端正常运行)并逐步运行时,它会在第28行中抛出异常,即ois = new ObjectInputStream(socket.getInputStream())。


感谢您发布了一个完整的、可编译的示例。我拿了您的代码在Eclipse中运行,没有抛出任何异常。可能是您的网络配置有些问题。您尝试过在调试器中逐步执行代码吗? - Jim Garrison
@Wyzard,这通常表示应用程序协议问题。 - user207421
@JimGarrison 我还没有尝试过,但是当我使用String类而不是user时,它可以工作,所以我认为这不是网络问题。我会尝试调试。谢谢 :) - user964843
奇怪了:当我在客户端中设置断点(服务器正常运行)并逐步执行时,它可以工作。但是,当我在服务器端设置断点(客户端正常运行)并逐步执行时,在第28行ois = new ObjectInputStream(socket.getInputStream()); 中会抛出异常。@JimGarrison,请问您知道这是为什么吗? - user964843
我没有刷新数据,所以它没有起作用。感谢ejp :) - user964843
显示剩余2条评论
1个回答

0
我知道我需要将包含我要发送的对象的类放在同一个包中。
不,除非你指的是“与自身相同的包”,这很简单。
它们应该有相同的serialVersionUID。
是的。
并且实现Serializable接口。
是的。
我已经做到了,但我仍然无法通过套接字发送对象。我哪里出错了?
你没有正确关闭客户端类中的套接字,所以连接被重置了。关闭输出流而不仅仅是刷新它。

当客户端结束时,套接字将被关闭。在Eclipse中代码运行良好,因此其他地方出了问题。 - Jim Garrison
@JimGarrison 不是的,这取决于平台。Windows会重置连接,Unixen会正确关闭套接字。OP的问题就在这里。代码在你的 Eclipse* 上运行良好,但只限于你的平台。 - user207421
这恰好是Win7。 - Jim Garrison
@JimGarrison 在我的 Netbeans JDK 1.8 Windows 7 Pro 上失败了。如果他采用这个修复方法,那么对于 OP 来说是有效的。真的很好奇。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接