Reputation: 47
When i use DataOutputStream/DataInputStream in my Server-Client Program everything goes fine but until I decided to use ObjectInputStream/ObjectOutputStream I had a problem while creating ObjectInputStream/ObjectOutputStream. Me and my friend couldn't see where the problem is. If anyone has any idea it would be thankful. Here is my "MyClient" and "MultiThreadServer" Classes.
It exactly stucks at the line : "fromServer = new ObjectInputStream(s.getInputStream());" line in MyClient Class.
Here is my "MyClient" Class:
public class MyClient extends javax.swing.JFrame {
String name;
public MyClient() {
initComponents();
sendButton.addActionListener(new ButtonListener());
jTextField1.addActionListener(new ButtonListener());
try{
Socket s = new Socket("localhost", 8080); // program reaches to this step
fromServer = new ObjectInputStream(s.getInputStream()); // and gets stuck in this step. (Understand it with using some Sys.out.print();)
toServer = new ObjectOutputStream(s.getOutputStream());
}
catch(Exception ex){
System.out.println("Something happend while socket is creating!");
}
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
name = jTextField2.getText();
}
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(MyClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(MyClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(MyClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(MyClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MyClient().setVisible(true);
}
});
}
private ObjectOutputStream toServer;
private ObjectInputStream fromServer;
private class ButtonListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent ae) {
// Here there are some activities when the button is clicked.
}
}
}
and here is my "MutliThreadServer" Class:
public class MultiThreadServer {
private String secretWord;
public Socket s;
public ArrayList clients = new ArrayList<ObjectOutputStream>();
ServerSocket serverSocket;
public static void main(String[] args) {
new MultiThreadServer();
}
public MultiThreadServer() {
try {
serverSocket = new ServerSocket(8080);
System.out.println("MultiThreadServer started at " + new Date() + '\n');
int clientNo = 1;
while (true) {
s = serverSocket.accept();
System.out.println("Starting thread for client " + clientNo +" at " + new Date() + '\n');
InetAddress inetAddress = s.getInetAddress();
System.out.println("Client " + clientNo + "'s host name is "+ inetAddress.getHostName() + "\n");
System.out.println("Client " + clientNo + "'s IP Address is "+ inetAddress.getHostAddress() + "\n");
HandleAClient task = new HandleAClient(s);
new Thread(task).start();
clientNo++;
}
}
catch(IOException ex) {
System.err.println(ex);
}
}
class HandleAClient implements Runnable {
private Socket socket;
public HandleAClient(Socket socket) {
this.socket = socket;
}
/** Run a thread */
public void run() {
try {
ObjectInputStream inputFromClient = new ObjectInputStream(
socket.getInputStream());
ObjectOutputStream outputToClient = new ObjectOutputStream(
socket.getOutputStream());
clients.add(outputToClient);
outputToClient.writeObject(arrayToString(secretWordArray));
// Continuously serve the client
while (true) {
// some unnecessary things that server makes
}
}
}
}
Upvotes: 0
Views: 391
Reputation: 53684
This is a classic "gotcha" when using Object Stream's over sockets. The Object stream format has a header which gets written by the constructor of ObjectOutputStream and read by the constructor of ObjectInputStream. So, your constructor call is blocking trying to read the header from the socket (which hasn't been written yet because the other end is likewise blocked.
Solution (for both ends of the connection):
flush()
the ObjectOutputStreamThis will ensure that the Object stream header gets written to the socket and sent to the receiver so that the ObjectInputStreams can be successfully constructed.
Upvotes: 2