在Socket.getInputStream之前向SocketInputStream发送内容?

时间:2016-11-16 00:44:05

标签: java multithreading sockets

我刚才遇到了一个奇怪的错误。我正在玩Serializable对象,我使用两个对象,通过Socket连接相互通信。两个应用程序是相同的(对等2对等),但有两个实例正在运行并尝试通信。

问题似乎围绕从套接字ObjectInputStream获取InputStream。我的错误发生在reader = new ObjectInputSream(cliIn),我被抛出一个SocketTimeoutException(这在我自己很奇怪,我希望read()在装饰我的流时没有。下面就是我试图做的事情

Socket clientSocket;
clientSocket = new Socket(InetAddress.getByName(aHostIP), aPort);
clientSocket.setSoTimeout(3000);

InputStream cliIn = clientSocket.getInputStream();
ObjectInputStream reader = null;
reader = new ObjectInputStream(cliIn); // <--- Error here
ObjectOutputStream writer;
writer = new ObjectOutputStream(new BufferedOutputStream(
     clientSocket.getOutputStream()
));

writer.writeObject(new Request(aPort));
writer.flush();

奇怪的是,如果我移动ObjectInputStream的创建直到我写入OutputStream之后(此时另一个对象会响应请求),那么就没有了更多错误。

Socket clientSocket;
clientSocket = new Socket(InetAddress.getByName(aHostIP), aPort);
clientSocket.setSoTimeout(3000);   

ObjectOutputStream writer;
writer = new ObjectOutputStream(new BufferedOutputStream(
     clientSocket.getOutputStream()
));

writer.writeObject(new Request(aPort));
writer.flush();

InputStream cliIn = clientSocket.getInputStream();
ObjectInputStream reader = null;
reader = new ObjectInputStream(cliIn); // <--- No more error

另一方(回应方)看起来像这样:

ObjectInputStream in = new ObjectInputStream(aConnection.getInputStream());
Object req = in.readObject();
SysIO.print("FROM OBJECT! : " + req.toString());
SysIO.print("FROM OBJECT! Port: " + ((Request) req).getPort());

Request res = new Request(15);

ObjectOutputStream out = new ObjectOutputStream(
      new BufferedOutputStream(aConnection.getOutputStream()));
out.writeObject(res);
out.flush();

它现在有效,但我很想知道这个问题是什么,以备将来参考。我可以看到,可能很难确切地说,但也许你有一些指针需要进一步调查,并发问题,我使用套接字或缓冲区是错误的吗?

(我遗漏了一些错误处理,使其更清晰。)

1 个答案:

答案 0 :(得分:0)

答案在ObjectInputStream documentation

public ObjectInputStream(InputStream in)
                  throws IOException
     

创建一个从指定的InputStream读取的ObjectInputStream。 从流中读取序列化流标头并进行验证。此构造函数将阻塞,直到相应的ObjectOutputStream已写入并刷新标头

     

如果安装了安全管理器,则此构造函数将检查&#34; enableSubclassImplementation&#34; SerializablePermission由子类的构造函数直接或间接调用,该子类重写ObjectInputStream.readFields或ObjectInputStream.readUnshared方法。

     

参数:

     

in - 从

读取的输入流      

抛出:

     

StreamCorruptedException - 如果流标头不正确

     

IOException - 如果在读取流标题时发生I / O错误

     

SecurityException - 如果不信任的子类非法覆盖安全敏感方法

     

NullPointerException - 如果in为空

在构造期间,流正在尝试从套接字读取序列化标头,但套接字读取超时,因为另一方尚未发送任何序列化对象。