我的服务器结尾处有以下代码:
public class ClientThread extends Thread
{
Socket clientSocket;
DataInputStream dis;
ObjectInputStream ois;
DataOutputStream dos;
public ClientThread(Socket acceptedSocket)
{
clientSocket = acceptedSocket;
try
{
dis = new DataInputStream(clientSocket.getInputStream());
ois = new ObjectInputStream(clientSocket.getInputStream()); // HANGS HERE
dos = new DataOutputStream(clientSocket.getOutputStream());
}
catch (Exception e)
{
System.out.println("ClientThread " + e.getMessage());
}
}
课程的其余部分省略
为什么我的应用程序在调用套接字输入流两次时会冻结,而不会抛出异常?
是的,我可以将输入流保存到InputStream变量并使用该变量来获取所需的输入流类型,但我很好奇为什么它在从套接字调用两次时会挂起?
有什么区别?被叫两次并没有改变什么?
编辑:即使将输入流保存到InputStream变量并使用该变量来获取所需的输入流(DataInputStream和ObjectInputStream),它仍会在多次调用时挂起?
示例:
public class ClientThread extends Thread
{
Socket clientSocket;
InputStream is;
DataInputStream dis;
ObjectInputStream ois;
DataOutputStream dos;
public ClientThread(Socket acceptedSocket)
{
clientSocket = acceptedSocket;
try
{
is = clientSocket.getInputStream();
dis = new DataInputStream(is);
ois = new ObjectInputStream(is); // STILL HANGS HERE
dos = new DataOutputStream(clientSocket.getOutputStream());
}
catch (Exception e)
{
System.out.println("ClientThread " + e.getMessage());
}
}
课程的其余部分省略
客户端代码:
public class LoginLogic_Callable implements Callable<String>
{
Socket socket;
String actionString;
String username;
String password;
public LoginLogic_Callable(Socket sentSocket, String sentUsername, String sentPassword)
{
socket = sentSocket;
username = sentUsername;
password = sentPassword;
}
@Override
public String call() throws Exception
{
String userLoginStatus = null;
try
{
DataOutputStream loginUserData = new DataOutputStream(socket.getOutputStream());
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
DataInputStream dis = new DataInputStream(socket.getInputStream());
String[] loginUserInfo = new String[2];
loginUserInfo[0] = username;
loginUserInfo[1] = password;
loginUserData.writeUTF("userlogin");
oos.writeObject(loginUserInfo);
loginUserData.flush();
oos.flush();
userLoginStatus = dis.readUTF();
loginUserData.close();
oos.close();
dis.close();
}
catch (Exception e)
{
}
return userLoginStatus;
}
}
答案 0 :(得分:2)
只是调用getInputStream()
不是'正在阅读',它不会导致此问题。您可以通过调用它十次,或者构造十次DataInputStreams
来证明它。导致问题的是ObjectInputStream
的构造,您可以通过完全删除DataInputStream
来证明 ,无论如何都应该这样做:见下文。
您正在创建ObjectInputStream
。 ObjectInputStream
的构造函数读取由ObjectOutputStream
的构造函数写入的流标头。由于这在代码中没有发生,并且可能不在同行中,它会永远阻止。
出于同样的原因,您必须先在ObjectOutputStream
之前创建ObjectInputStream
,否则您将再次陷入僵局。
这里似乎有一些计划在同一个套接字上使用两种流。不要那样做。它不起作用,并且没有必要,因为除了对象读写方法之外,对象流具有与数据流相同的所有方法。
编辑既然您已发布了客户端代码,那么客户端正在推迟创建ObjectOutputStream
,直到调用call()
为止。它应该在该类的构造函数中创建。否则,服务器端构造函数会阻塞,直到客户端调用call()
为止。你仍然需要摆脱多余的流。