带套接字的 ObjectStreams 在服务器端和客户端挂起 java
ObjectStreams with sockets hang at server and client side java
我有这个代码:
package com.company;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
class MyClass implements Serializable
{
private int i,j;
public MyClass(int i, int j)
{
this.i = i;
this.j = j;
}
public int getJ()
{
return j;
}
public void setJ(int j)
{
this.j = j;
}
public int getI()
{
return i;
}
public void setI(int i)
{
this.i = i;
}
}
class ServerThread extends Thread
{
ServerSocket server;
public ServerThread() throws IOException
{
server=new ServerSocket(14200);
}
@Override
public void run()
{
try
{
Socket client=server.accept();
ObjectInputStream in=new ObjectInputStream(client.getInputStream());
ObjectOutputStream out=new ObjectOutputStream(client.getOutputStream());
int i=in.readInt();
MyClass m=(MyClass)in.readObject();
if(i==m.getI())
{
m.setJ(i);
out.writeObject(m);
}
else
{
m.setI(i);
out.writeObject(m);
}
out.writeUTF("see ya");
}
catch (IOException | ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
public class Main
{
public static void main(String... args) throws IOException, ClassNotFoundException
{
ServerThread serverThread=new ServerThread();
serverThread.setDaemon(true);
serverThread.start();
Socket client=new Socket("localhost",14200);
ObjectInputStream in=new ObjectInputStream(client.getInputStream());
ObjectOutputStream out=new ObjectOutputStream(client.getOutputStream());
out.writeInt(2);
out.writeObject(new MyClass(4,2));
MyClass m=(MyClass)in.readObject();
String s=in.readUTF();
System.out.println(s);
}
}
我的问题是客户端和服务器都挂在这条线上:
ObjectInputStream in=new ObjectInputStream(client.getInputStream);
如果我为套接字设置超时,我会得到 SocketTimeoutException。
真实目标
上面的程序只是一个虚拟程序,但显示了我的问题,真正的程序是一个用于共享文件的服务器-客户端应用程序,我在其中实现了自己的简单协议,这实际上是一个家庭作业。
我们被要求实现数字签名,我创建了自己的助手 classes,最后我得到了 SignatureWithPublicKey class(由我定义),它包含签名字节和 public 键,我需要通过套接字发送这个对象。
一个简单的解决方案是将 PublicKey.getEncoded 与签名字节一起发送但是我想使用 ObjectStreams,我需要知道它们为什么不工作。
那么这里的问题是什么?
Object 流有一个小 header。这意味着在发送和读取 header 之前,您甚至无法启动 object 输入流。但是,在您调用 ObjectOutputStream 之前,您的代码不会发送 header,在这种情况下,您是在输入流之后执行的。即你有一个死锁。
简而言之,在这两种情况下交换 new ObjectInputStream
和 new ObjectOutputStream
的顺序。
我有这个代码:
package com.company;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
class MyClass implements Serializable
{
private int i,j;
public MyClass(int i, int j)
{
this.i = i;
this.j = j;
}
public int getJ()
{
return j;
}
public void setJ(int j)
{
this.j = j;
}
public int getI()
{
return i;
}
public void setI(int i)
{
this.i = i;
}
}
class ServerThread extends Thread
{
ServerSocket server;
public ServerThread() throws IOException
{
server=new ServerSocket(14200);
}
@Override
public void run()
{
try
{
Socket client=server.accept();
ObjectInputStream in=new ObjectInputStream(client.getInputStream());
ObjectOutputStream out=new ObjectOutputStream(client.getOutputStream());
int i=in.readInt();
MyClass m=(MyClass)in.readObject();
if(i==m.getI())
{
m.setJ(i);
out.writeObject(m);
}
else
{
m.setI(i);
out.writeObject(m);
}
out.writeUTF("see ya");
}
catch (IOException | ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
public class Main
{
public static void main(String... args) throws IOException, ClassNotFoundException
{
ServerThread serverThread=new ServerThread();
serverThread.setDaemon(true);
serverThread.start();
Socket client=new Socket("localhost",14200);
ObjectInputStream in=new ObjectInputStream(client.getInputStream());
ObjectOutputStream out=new ObjectOutputStream(client.getOutputStream());
out.writeInt(2);
out.writeObject(new MyClass(4,2));
MyClass m=(MyClass)in.readObject();
String s=in.readUTF();
System.out.println(s);
}
}
我的问题是客户端和服务器都挂在这条线上:
ObjectInputStream in=new ObjectInputStream(client.getInputStream);
如果我为套接字设置超时,我会得到 SocketTimeoutException。
真实目标
上面的程序只是一个虚拟程序,但显示了我的问题,真正的程序是一个用于共享文件的服务器-客户端应用程序,我在其中实现了自己的简单协议,这实际上是一个家庭作业。
我们被要求实现数字签名,我创建了自己的助手 classes,最后我得到了 SignatureWithPublicKey class(由我定义),它包含签名字节和 public 键,我需要通过套接字发送这个对象。
一个简单的解决方案是将 PublicKey.getEncoded 与签名字节一起发送但是我想使用 ObjectStreams,我需要知道它们为什么不工作。
那么这里的问题是什么?
Object 流有一个小 header。这意味着在发送和读取 header 之前,您甚至无法启动 object 输入流。但是,在您调用 ObjectOutputStream 之前,您的代码不会发送 header,在这种情况下,您是在输入流之后执行的。即你有一个死锁。
简而言之,在这两种情况下交换 new ObjectInputStream
和 new ObjectOutputStream
的顺序。