通过 ObjectInputStream 接收对象 (Java)
Recieving objects through ObjectInputStream (Java)
它是 java 中的 Messenger 应用程序。我想发送对象而不仅仅是文本,我认为这样更好。我正在为每个连接的客户端使用一个 ServerSocketChannel 和一个新线程。
-相同的包,相同的构造函数,相同的 serialVersionUID。
它只是打印出 "before" 命令,无法读取客户端的对象。
部分服务器代码:
public static void startServer(){
try{
ServerSocketChannel ssc=ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(hostName,portNumber));
while(isServerRunning()){
removeLoggedOutClients();
try{
SocketChannel sc=ssc.accept();
Socket s=sc.socket();
ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
Client cli=null;
System.out.println("before");
cli=(Client)ois.readObject();
System.out.println("after");
ois.close();
if(checkLogin(cli)){
System.out.println(cli.getUsername()+" signed in.");
cli.setSocket(s);
ClientThread ct=new ClientThread(s,cli.getClientID());
ct.setDaemon(true);
clientThreads.add(ct);
ct.start();
}
}
catch(Exception e){
Error err=new Error("Server","void startServer()",2,e.toString());
}
}
}
catch(Exception e){
Error err=new Error("Server","void startServer()",1,e.toString());
}
}
部分客户代码:
public static void connectToServer(Client user){
try{
SocketChannel sc=SocketChannel.open();
sc.configureBlocking(true);
sc.connect(new InetSocketAddress(serverHostName,serverPortNumber));
Socket s=sc.socket();
ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
oos.writeObject(user);
oos.flush();
RecieveThread rt=new RecieveThread(s,ois,user);
rt.setDaemon(true);
rt.start();
setOut(oos);
}
catch(Exception e){
Error err=new Error("Client","connectToServer(Client user)",1,e.toString());
}
}
(我的"Error" class的目的是将所有可能的异常插入数据库。)
主要问题是您在客户端中创建了一个 ObjectInputStream
:这将阻塞,直到在对等体中创建 ObjectOutputStream
,而您至少没有创建一个不在您发布的代码中。您需要立即在两端创建 ObjectOutputStream
,然后再创建 ObjectInputStream,
。
但是你还有一个问题。除了接受连接之外,你不应该在接受循环中做任何 I/O 。所有对象流的创建、登录等,都应该在为处理连接而创建的线程中完成,注意不是在其构造函数中,而是在其 run()
方法中。否则一个流氓或故障客户端可能会阻塞整个系统。
它是 java 中的 Messenger 应用程序。我想发送对象而不仅仅是文本,我认为这样更好。我正在为每个连接的客户端使用一个 ServerSocketChannel 和一个新线程。
-相同的包,相同的构造函数,相同的 serialVersionUID。
它只是打印出 "before" 命令,无法读取客户端的对象。
部分服务器代码:
public static void startServer(){
try{
ServerSocketChannel ssc=ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(hostName,portNumber));
while(isServerRunning()){
removeLoggedOutClients();
try{
SocketChannel sc=ssc.accept();
Socket s=sc.socket();
ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
Client cli=null;
System.out.println("before");
cli=(Client)ois.readObject();
System.out.println("after");
ois.close();
if(checkLogin(cli)){
System.out.println(cli.getUsername()+" signed in.");
cli.setSocket(s);
ClientThread ct=new ClientThread(s,cli.getClientID());
ct.setDaemon(true);
clientThreads.add(ct);
ct.start();
}
}
catch(Exception e){
Error err=new Error("Server","void startServer()",2,e.toString());
}
}
}
catch(Exception e){
Error err=new Error("Server","void startServer()",1,e.toString());
}
}
部分客户代码:
public static void connectToServer(Client user){
try{
SocketChannel sc=SocketChannel.open();
sc.configureBlocking(true);
sc.connect(new InetSocketAddress(serverHostName,serverPortNumber));
Socket s=sc.socket();
ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
oos.writeObject(user);
oos.flush();
RecieveThread rt=new RecieveThread(s,ois,user);
rt.setDaemon(true);
rt.start();
setOut(oos);
}
catch(Exception e){
Error err=new Error("Client","connectToServer(Client user)",1,e.toString());
}
}
(我的"Error" class的目的是将所有可能的异常插入数据库。)
主要问题是您在客户端中创建了一个 ObjectInputStream
:这将阻塞,直到在对等体中创建 ObjectOutputStream
,而您至少没有创建一个不在您发布的代码中。您需要立即在两端创建 ObjectOutputStream
,然后再创建 ObjectInputStream,
。
但是你还有一个问题。除了接受连接之外,你不应该在接受循环中做任何 I/O 。所有对象流的创建、登录等,都应该在为处理连接而创建的线程中完成,注意不是在其构造函数中,而是在其 run()
方法中。否则一个流氓或故障客户端可能会阻塞整个系统。