我的服务器端有以下代码:
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;
}
}
仅仅调用getInputStream()
并不是"读取",也不会导致此问题。你可以通过调用它十次,或者围绕它构造十个DataInputStreams
来证明这一点。正是ObjectInputStream
的构造导致了问题,你可以通过完全删除DataInputStream
来证明,无论如何你都应该这样做:见下文。
您正在创建ObjectInputStream
。ObjectInputStream
的构造函数读取由ObjectOutputStream
的构造函数写入的流报头。由于这段代码中没有发生这种情况,而且可能在对等端也没有发生,因此它将永远阻塞。
出于同样的原因,必须先创建ObjectOutputStream
,然后再创建ObjectInputStream
,否则将再次出现死锁。
这里似乎有一些在同一个套接字上使用两种流的计划。不要那样做。它不起作用,也没有必要,因为除了对象读取和写入方法外,对象流还有与数据流相同的方法。
EDIT现在您已经发布了客户端代码,此时客户端正在推迟创建ObjectOutputStream
,直到调用call()
。它应该在该类的构造函数中创建。否则,您的服务器端构造函数将阻塞,直到客户端调用call()
为止。您仍然需要消除多余的流。