Socket如何传递对象?
为了传递对象,我在建立连接的时候用了ObjectOutputStream和ObjectInputStream,代码如下:
out=new ObjectOutputStream (s.getOutputStream());
out.flush();
in=new ObjectInputStream(s.getInputStream());
这种连接中用out.writeObject()可以传递String对象。
但是,我现在想要用它传递一种自己定义类的对象,类定义如下:
class test {
String name;
int a;
int b;
public test(String s,int i,int j) {
name=s;
a=i;
b=j;
}
}
在对象初始化后,传递时提示出现NotSerializableException异常。
现在请问各位高手,如何才能实现test对象的传递?
注:Socket连接已经建立成功。
问题点数:100、回复次数:38Top
1 楼xf_luo(xiaofeng_luo)回复于 2005-05-11 20:16:32 得分 10
要序列化Top
2 楼xf_luo(xiaofeng_luo)回复于 2005-05-11 20:17:09 得分 0
自定义类要序列化Top
3 楼xf_luo(xiaofeng_luo)回复于 2005-05-11 20:20:56 得分 0
序列化的目的是:将一个对象的状态(各个属性量)保存起来,然后在适当的时候再获得.
传递对象必须要保存对象的状态,所以...
Top
4 楼wzd268(九霄之鹏)回复于 2005-05-11 20:28:37 得分 0
xf_luo(xiaofeng_luo),你说的保存对象的状态(各个属性量)是什么意思?
我有点不太明白。
Top
5 楼wzd268(九霄之鹏)回复于 2005-05-11 20:30:00 得分 0
再进一步,如何对类进行序列化?
能不能具体一点?Top
6 楼xf_luo(xiaofeng_luo)回复于 2005-05-11 20:38:24 得分 0
要序列化只要实现Serializable接口就可以了,implements java.io.SerializableTop
7 楼xf_luo(xiaofeng_luo)回复于 2005-05-11 20:45:04 得分 10
因为传递对象是先将对象转换为字节序列,这些字节序列可以被完全存储以备以后重新生成原来的对象.Top
8 楼wzd268(九霄之鹏)回复于 2005-05-11 20:58:44 得分 0
xf_luo(xiaofeng_luo),谢谢你
现在已经可以传递了,但是又出了一个新的问题:
SocketServer端找不到SocketClient.test类的定义
这个问题如何解决?
我会加分的Top
9 楼wzd268(九霄之鹏)回复于 2005-05-11 21:03:28 得分 0
在SocketServer端我已经定义了同样的一个test类
而且在读取对象的时候使用了如下语句:
t = (test) in.readObject();
再次拜托,谢谢!Top
10 楼wzd268(九霄之鹏)回复于 2005-05-11 21:18:48 得分 0
upTop
11 楼xf_luo(xiaofeng_luo)回复于 2005-05-11 21:42:02 得分 0
刚才出去了~!
当然你要在服务断也要定义这个类啊Top
12 楼xf_luo(xiaofeng_luo)回复于 2005-05-11 21:45:28 得分 0
test t = (test) in.readObject();Top
13 楼humanity(城市边缘的狼)回复于 2005-05-11 22:09:17 得分 10
1,实现 java.io.Serializable 接口 (必须的,你没有JVM 就认为你不想把敏感数据通过网络传送或写入磁盘)。
2 ,如果你的类定义了一对 void writeObject & void readObject , 如果你提供了这对方法, JVM 会自动调用它 来完成工作,如果没有定义这对方法,JVM 提供默认的行为。
3,serialVersionUID ... 保证 Socket 两端 使用的类 版本兼容 。Top
14 楼wzd268(九霄之鹏)回复于 2005-05-11 22:16:24 得分 0
to: xf_luo(xiaofeng_luo)
我在服务器端已经定义了这个类了,而且与Client端完全相同。
to:humanity(总是偷窥 Java & XML) ,你说的:
serialVersionUID ... 保证 Socket 两端 使用的类 版本兼容 。
如何具体实现?Top
15 楼xf_luo(xiaofeng_luo)回复于 2005-05-11 22:24:04 得分 0
兼容也就是版本控制问题,如果版本不一样的话就不能反序列,既然你服务端和客户端的类一样,就不会出现这个问题.
Top
16 楼wzd268(九霄之鹏)回复于 2005-05-11 22:33:59 得分 0
那么为什么会出现这个异常?
在test t = (test) in.readObject();之后
读取t的内容时出现ClassNotFoundException
Top
17 楼wzd268(九霄之鹏)回复于 2005-05-11 22:48:51 得分 0
看来问题要留到明天解决了
祝大家晚安!!Top
18 楼xf_luo(xiaofeng_luo)回复于 2005-05-12 08:38:54 得分 0
把代码贴出来吧Top
19 楼hongyan2004(spring+hibernate)回复于 2005-05-12 09:13:05 得分 0
implements java.io.SerializableTop
20 楼wzd268(九霄之鹏)回复于 2005-05-12 09:47:31 得分 0
test类的定义:
class test implements java.io.Serializable{
byte name;
int a;
int b;
public test(byte s,int i,int j) {
name=s;
a=i;
b=j;
}
}
Object输入输出流的建立:
out=new ObjectOutputStream (s.getOutputStream());
out.flush();
in=new ObjectInputStream(s.getInputStream());
我觉得问题的关键在这里:
在Client端,我用上述代码定义了一个test类,
在Server端,我也用上述代码定义了一个类。
但是,虽然两端类的定义是完全一样的,由于他们处于不同的工程中,
代码相同并不代表Server端可以识别Client端的test类;
所以在Client端发送test对象时,Server端会发出
ClassNotFoundException异常,找不到SocketClient.test类
Top
21 楼xf_luo(xiaofeng_luo)回复于 2005-05-12 10:50:37 得分 0
这个跟工程没关系,
你只要保证类的版本一样就可以,在服务端只是进行反序列化.
你看是不是socket建立不成功,对象没有传过来Top
22 楼wzd268(九霄之鹏)回复于 2005-05-12 11:04:33 得分 0
socket建立成功了,我先前用String测试过。
类的版本一样就是指他们的定义代码相同吗?
是不是和humanity(总是偷窥 Java & XML)所说的serialVersionUID有所关系?
如果是的话,怎样具体实现?Top
23 楼wzd268(九霄之鹏)回复于 2005-05-12 17:13:13 得分 0
出现异常
ClassCastException
如何消除?Top
24 楼usabcd(9号公路上的3名共军)回复于 2005-05-12 18:55:52 得分 10
传对象是很普通的事,有什么特别的吗?
写了一个小例子供楼主参考。
对象:
public class TestObject implements java.io.Serializable {
public String getString(){
return "Hello World!";
}
}
客户端
import java.io.ObjectOutputStream;
import java.net.Socket;
public class ObjectClient {
public static void main(String argv[]) throws Exception {
Socket s = new Socket("192.168.18.103", 14567);
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
oos.writeObject(new TestObject());
oos.flush();
System.out.println("Send finished.");
}
}
服务端:
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ObjectServer {
public static void main(String arg[]) throws Exception {
int port = 14567;
ServerSocket socket = new ServerSocket(port);
System.out.println("Server is running on " + port);
System.out.println("Press [Ctrl+C] to abort");
while (true) {
Socket s = socket.accept();
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
TestObject to = (TestObject) ois.readObject();
String str = to.getString(); // use object passed from client
System.out.println(str + " from " + s.getInetAddress());
}
}
}
经过调试通过。
Top
25 楼nimifeng(学海无涯.......苦作舟....理解是美!!!Mars.Neil)回复于 2005-05-12 19:06:57 得分 10
学习..帮顶.Top
26 楼wzd268(九霄之鹏)回复于 2005-05-12 19:42:09 得分 0
usabcd(9号公路上的3名共军) :
首先非常感谢你!
但我对你的程序有几个疑问:
你所说的调试通过是不是在同一台机器上?三个类在同一个目录中?
当传递对象所对应类的定义在不同的目录或不同主机下的时候
对象的反序列化会出现异常
ClassCastExceptionTop
27 楼usabcd(9号公路上的3名共军)回复于 2005-05-12 20:11:27 得分 0
跟目录、在不在一台机应该是没关系的,你先放到不同的机器试一下看看。
我手头只有一台机没办法试。
Top
28 楼wzd268(九霄之鹏)回复于 2005-05-12 20:22:21 得分 0
我在JB9下试过了,用TestObject和ObjectClient建立一个工程
TestObject和ObjectServer建立另一个工程
以下是Server端的运行结果:
Server is running on 14567
Press [Ctrl+C] to abort
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:168)
at java.net.SocketInputStream.read(SocketInputStream.java:182)
at java.io.ObjectInputStream$PeekInputStream.peek(ObjectInputStream.java:2133)
at java.io.ObjectInputStream$BlockDataInputStream.readBlockHeader(ObjectInputStream.java:2316)
at java.io.ObjectInputStream$BlockDataInputStream.refill(ObjectInputStream.java:2383)
at java.io.ObjectInputStream$BlockDataInputStream.skipBlockData(ObjectInputStream.java:2288)
at java.io.ObjectInputStream.skipCustomData(ObjectInputStream.java:1795)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1519)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1435)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1626)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1274)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:324)
at untitled2.ObjectServer.main(ObjectServer.java:25)
Exception in thread "main"Top
29 楼wzd268(九霄之鹏)回复于 2005-05-12 20:26:36 得分 0
untitled2.ObjectServer.main(ObjectServer.java:25)
所指的代码为:
TestObject to = (TestObject) ois.readObject();
Top
30 楼usabcd(9号公路上的3名共军)回复于 2005-05-12 21:00:04 得分 0
把客户端延迟一下看看,比如发完后等2秒 Thread.sleep(3000)Top
31 楼chinawzcxy(方程式指挥官)回复于 2005-05-12 21:04:52 得分 0
www.xydir.comTop
32 楼usabcd(9号公路上的3名共军)回复于 2005-05-12 22:31:31 得分 10
我刚找了2台机试了, 客户端加个延迟就没问题了。
当然你可以选个小一点的延迟,不一定是3秒。
import java.io.ObjectOutputStream;
import java.net.Socket;
public class ObjectClient {
public static void main(String argv[]) throws Exception {
Socket s = new Socket("192.168.18.103", 14567);
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
oos.writeObject(new TestObject());
oos.flush();
Thread.sleep(3000);
System.out.println("Send finished.");
}
}
Top
33 楼wzd268(九霄之鹏)回复于 2005-05-13 16:36:03 得分 0
试过了,出现了新的异常,这也是我原来所遇到的
java.lang.ClassNotFoundException: untitled1.TestObject
untitled1是Client端所在的工程。
TestObject类定义虽然一样,但是由于分别在Client端和Server端定义
JVM并不认为他们相同,所以在反序列化的时候会出现异常Top
34 楼usabcd(9号公路上的3名共军)回复于 2005-05-13 18:39:36 得分 0
服了你了,我都帮你找2台机子试过OK了,你还。。。Top
35 楼nimifeng(学海无涯.......苦作舟....理解是美!!!Mars.Neil)回复于 2005-05-13 20:36:23 得分 10
test t = (test) in.readObject();这样只有服务器有类就可以识别了.Top
36 楼oscaryue()回复于 2005-05-15 00:17:18 得分 10
实现Serializable接口Top
37 楼anguskwan()回复于 2005-05-15 01:40:20 得分 10
如果服务端接受成功的话,返回一个信息啊~~否则loop咯~~
在不同机器上的时候注意防火墙的问题。Top
38 楼gtlang78()回复于 2005-05-15 01:54:36 得分 10
TestObject类的包名也要相同啊Top




