Create ObjectInputStream according to a socket - java

I'm trying to create an ObjectInputStream according to a Socket and add this stream into a List.
The client is connected in the main class of my program, and the socket is sent in an other method in a Thread. Then the socket is used to create the stream.
The problem is that the stream is never create. I don't get why...
Below is my code :
In my Thread :
public void addClient(Socket socket){
try{
streamList.add(new ObjectInputStream(socket.getInputStream()));
}catch(IOException e){
e.printStackTrace();
}
}
And in my main class :
ServerSocket serverSocket = new ServerSocket(PORT);
Socket socket;
ClientThread clientThread = new ClientThread();
//start the thread
try{
socket = serverSocket.accept();
clientThread.addClient(socket);
}
catch(IOException e){
e.printStackTrace();
}
Thanks in advance.

The peer needs to create his ObjectOutputStream immediately on connection. Otherwise new ObjectInputStream will block until he does so.
It would be better if you could defer creation of the ObjectInputStream to the run() method of the thread that handles the accepted socket. You shouldn't do any I/O in the accept loop, just the accept itself. Otherwise you can block subsequent clients.

Related

SocketServer keeps accepting same connection. Creating multiple threads for that same connection

I'm creating a simple http server. I have a master thread that waits in a loop for a connection to be accepted. Once a connection is accepted, I create a new worker thread to handle the connection, passing the accepted socket as an argument. Once a connection is accepted, a new thread is created for it, however the master thread will loop again, create another socket with the same connection and create another duplicated thread.
Master thread waiting for connections.
public void run(){
while(Tester.serverStatus != "quit"){
try {
Socket clientSocket = serverSocket.accept();
new Thread(new Worker(clientSocket)).start();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
this.stop();
} catch (IOException e) {
e.printStackTrace();
}
return;
}
public void stop() throws IOException{
serverSocket.close();
return;
}
Worker thread pseudocode
public void run(){
InputStream input = clientSocket.getInputStream();
//read from stream, validate request and setup the response in a byte array
input.close();
DataOutputStream output = new DataOutputStream(clientSocket.getOutputStream());
output.write(responseByteArray);
output.flush();
output.close();
clientSocket.close();
return;
}
Any ideas as to why the accept() method isn't being blocked after the first connection is accepted? It just keeps on creating duplicate Worker threads with the same Socket.
Thanks
What you describe is not possible.
You undoubtedly have some static variables somewhere that should be instance members of Worker, such as the input and/or output streams, and/or the socket itself.

app get stuck at serverSocket.accept() and gives bind exception address already in use on the second call for the thread

I have two problems with an app that i have built for socket communication, first I'll try to explain what the app does and then I'll go into the details of those two problems.
First I click on a button, which starts a thread, which sends a multicast massage "group address" through a UDP socket. Once any of the devices receive the massage, they will send a response through TCP socket and my device will act as a server to the one that sent the response. So after debugging I found out the first problem which is clientSocket = serverSocket.accept(); sometimes gets stuck and the app will block everything and keep executing it, which might happen because the udp massage might never arrive at the destination which means there is no client for the tcp server that I've created.
First question: Is there any way to make the serverSocket.accept(); non-blocking or set a time out? I've tried serverSocket.setTimeSoOut() method, but that didn't work. Maybe this problem comes from something other than the UDP message?
The second problem is that if I press the button that calls the thread twice it will throw a BindException address already in use: Which will happen because of the re execution of serverSocket.bind(new InetSocketAddress(4125));. Is there any way to fix/avoid that?
Here are the threads that I'm using:
This one is called after I press the button:
private class ChatClientThread extends Thread {
DatagramSocket socket;
String sentence;
String modifiedSentence;
BufferedReader inFromUser;
DataOutputStream outToServer;
BufferedReader inFromServer;
Socket clientSocket;
ServerSocket serverSocket;
#Override
public void run() {
/*Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream=null;*/
clientSocket=null;
try {
String data="NewTask_"+EmpPhoneNumber;
serverSocket=new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(4125));
socket = new DatagramSocket(52276);
socket.setBroadcast(true);
InetAddress group = InetAddress.getByName(
"224.0.1.2");
DatagramPacket packet = new DatagramPacket(data.getBytes(), data.length(),
group, 52276);
socket.send(packet);
while(true){
clientSocket = serverSocket.accept();
ConnectThread ct=new ConnectThread(clientSocket);
ct.start();
}
} catch (UnknownHostException e) {
e.printStackTrace();
final String eString = e.toString();
TicketDetails.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(TicketDetails.this, eString, Toast.LENGTH_LONG).show();
}
});
} catch (IOException e) {
e.printStackTrace();
final String eString = e.toString();
TicketDetails.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(TicketDetails.this, eString, Toast.LENGTH_LONG).show();
}
});
} finally {
TicketDetails.this.runOnUiThread(new Runnable() {
#Override
public void run() {
}
});
}
}
}
this one is called from the above thread as you can see:
private class ConnectThread extends Thread {
Socket socket;
String sentence;
String modifiedSentence;
BufferedReader inFromUser;
DataOutputStream outToServer;
BufferedReader inFromServer;
ConnectThread(Socket socket){
this.socket= socket;
}
#Override
public void run() {
DataInputStream dataInputStream = null;
DataOutputStream dataOutputStream = null;
Socket socket2 = null;
DataOutputStream dataOutputStream2= null;
DataInputStream dataInputStream2=null;
try {
while(true){
inFromUser = new BufferedReader( new InputStreamReader(System.in));
outToServer = new DataOutputStream(socket.getOutputStream());
inFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
sentence = inFromUser.readLine();
modifiedSentence = inFromServer.readLine();
socket2 = new Socket(socket.getInetAddress().getHostAddress(), 4125);
dataOutputStream2 = new DataOutputStream(
socket2.getOutputStream());
String[] parts = modifiedSentence.split("_");
String partGive = parts[0].substring(4); // 004
String partEmpId = parts[1];
if(partGive.equals("GiveMeATask")&&Integer.parseInt(partEmpId)==empId){
dataOutputStream2.writeUTF(" "+"SolveProblemOrder_2");
dataOutputStream2.flush();
}
System.out.println("FROM SERVER: " + modifiedSentence);
if(modifiedSentence!=null) break;}
outToServer.close();
inFromServer.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
Those are two very commmon problems. I'll answer the two in reverse order.
The button you are talking about is creating a ServerSocket and binding it to a specific port. In your case, the port is 4125. From looking at your code, you don't seem to be closing that serversocket anywhere. When you click the button a second time, a second instance of ServerSocket tries to bind to the same port - but that port is still in use by the first ServerSocket. In that case, you get a bind exception. One port cannot be used by more than one ServerSocket. The solution would be to close the existing ServerSocket before creating a new one using serverSocket.close();
If you read the documentation, it clearly states what ServerSocket.accept() does: "[...] The method blocks until a connection is made." This is the "getting stuck" that you described. The thread that executes that code is put into a waiting position and continues only when a connection is made, then returns that new connection. The classic approach is to start a new thread that waits for incoming connections so that your main thread continues to execute and your whole application does not "freeze". Another approach would be a non-blocking framework that encapsulates all that overhead away from you, one of those is Apache MINA.
I would highly suggest to look into small example projects that deal with basic client/server behaviour as you will most likely deal with threads here.
First problem: It is very likely that your application is not receiving the UDP packages. If serverSocket.accept() doesn't get any clients it'll wait indefinitely for someone to connect. You could avoid this by using yet another thread that just accepts connections to avoid freezing your application. Another way would be to use Java's NIO classes that provide non-blocking IO for pretty much anything. That would require you to use ServerSocketChannel and related classes. (Quick googling also gave me this guide which seems fairly easy to follow).
Second problem: You need to close your ServerSocket once you're done using it. Otherwise the port will never be free again to be used by another ServerSocket.
Alternatively you could just leave the Socket open and remember that you already openend it (e.g. with a boolean field in your class).

Recieving objects through ObjectInputStream (Java)

It's a messenger application in java. I want to send objects and not just text, I think it's much better. I'm using a ServerSocketChannel and a new Thread for every connected client.
-Same package, same constructor, same serialVersionUID.
It just prints out the "before" command, can't read the Client's object.
Part of the server's code:
public static void startServer(){
try{
ServerSocketChannel ssc=ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(hostName,portNumber));
while(isServerRunning()){
removeLoggedOutClients();
try{
SocketChannel sc=ssc.accept();
Socket s=sc.socket();
ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
Client cli=null;
System.out.println("before");
cli=(Client)ois.readObject();
System.out.println("after");
ois.close();
if(checkLogin(cli)){
System.out.println(cli.getUsername()+" signed in.");
cli.setSocket(s);
ClientThread ct=new ClientThread(s,cli.getClientID());
ct.setDaemon(true);
clientThreads.add(ct);
ct.start();
}
}
catch(Exception e){
Error err=new Error("Server","void startServer()",2,e.toString());
}
}
}
catch(Exception e){
Error err=new Error("Server","void startServer()",1,e.toString());
}
}
Part of the client's code:
public static void connectToServer(Client user){
try{
SocketChannel sc=SocketChannel.open();
sc.configureBlocking(true);
sc.connect(new InetSocketAddress(serverHostName,serverPortNumber));
Socket s=sc.socket();
ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
oos.writeObject(user);
oos.flush();
RecieveThread rt=new RecieveThread(s,ois,user);
rt.setDaemon(true);
rt.start();
setOut(oos);
}
catch(Exception e){
Error err=new Error("Client","connectToServer(Client user)",1,e.toString());
}
}
(The purpose of my "Error" class is to insert all possible exceptions to database.)
The main problem is that you're creating an ObjectInputStream in the client: this will block until the ObjectOutputStream in the peer is created, and you're not creating one, at least not in the code you posted. You need to create the ObjectOutputStream and then the ObjectInputStream, immediately, in that order, at both ends.
However you have a further problem. You shouldn't do any I/O whatsoever in the accept loop other than accepting connections. All the object stream creation, login, etc., should be done in the thread created to handle he connection, and NB not in its constructor but in its run() method. Otherwise one rogue or malfunctioning client can block the whole system.

Threads and Handlers in server socket

How is the new Handler(clientSocket); instantiated without an object?. Can somebody give some insight?
public class Server1 {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(15897);
while (true) {
Socket clientSocket = serverSocket.accept();
new Handler(clientSocket);
}
} catch (IOException e)
{
System.out.println("problem here 1");
}
}
}
class Handler implements Runnable {
int red;
int reads, r;
Socket clientSocket;
Handler(Socket s)
{
this.clientSocket = s;
new Thread(this).start();
}
public void run(){
BufferedReader bufferedReader;
try {
bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine = bufferedReader.readLine();
In you code Server is made to keep listening the incoming Clients.
Socket clientSocket = serverSocket.accept();
serverSocket.accept() waits until a connection or a client is found.
If client is found then accept() function returns a local socket which is connected to another socket at the client which is given to clientSocket in you code.
new Handler(clientSocket);
Now clientSocket is given to Handler class in which you are using thread for reading the data given by that clientSocket.
The purpose of thread here is to handle each incoming clientSocket seprately.
Your code is incomplete, so it's difficult to say with certainty, but observe that in the Handler's constructor a thread is created and started, which executes run().
Inside that function (and therefore in a separate thread), the input stream is read from the socket into a BufferedReader, from which the first line is obtained.
The thread will block until a line is received over the socket connection.
Because your code is cut off from that point, I can't say what else it does.
I am not sure what exactly does the code do but explaining it to you as per the concept of OOPs, it creates an instance of the Handler class everytime the while loop is executed.
Warning: The while(true) loop is bad code and when the project is run, it will run in an infinite loop.

ObjectInputStream won't initialize when using BufferedOutputStreams

I am trying to send objects across a socket for a game, but they take a long time to send and can cause the game to hang. I want to use BufferedOutputStreams and BufferedInputStreams to send the data, but my ObjectInputStream won't initialize on the server side when I use the BufferedOutputStream on the client side. The weird thing is that no errors are thrown.
I'm only providing the code involved because it would take a long time to explain what's going on otherwise. Two clients are initialized each game.
/*Server Code*/
ObjectOutputStream toClients;//stream to both players
ObjectInputStream fromClients;//stream from both players
Socket client1;//player one socket
Socket client2;//player two socket
public RunGame(Socket client1, Socket client2)throws IOException//constructor of a new thread
{
this.client1=client1;
this.client2=client2;
}
public void run()//for the thread
{
try{
this.createGame();
/*
rest of code for server when running game
*/
}
catch(IOException e){e.printStackTrace();}
catch(ClassNotFoundException e){e.printStackTrace();}
}
public void createGame()
{
try{
System.out.println("about to create");//this prints out
fromClients=new ObjectInputStream(client1.getInputStream());//first initialization
System.out.println("created");//this doesn't
String s1=(String)fromClients.readObject();
fromClients=new ObjectInputStream(client2.getInputStream());//sets input to player 2
String s2=(String)fromClients.readObject();
}
catch(IOException e){e.printStackTrace();}
catch(ClassNotFoundException e){e.printStackTrace();}
}
/*Client Code*/
Socket sock;//created in the constructor of the thread
ObjectOutputStream toServer;
ObjectInputStream fromServer;
public void run()
{
try{
System.out.println("about to create");//this prints
toServer=new ObjectOutputStream(new BufferedOutputStream(sock.getOutputStream(),8*1024));//bufferedoutputstream is here
toServer.writeObject("String that is to be sent to server");
System.out.println("written");//this also prints
}
catch(IOException e){e.printStackTrace();}
catch(ClassNotFoundException e){e.printStackTrace();}
/*
rest of client code
*/
}
I've been through all of the forums but can't find anything that works, which makes me assume that I'm doing something very novice. Thanks for any help you can give!
You'll need to .flush() your ObjectOutputStream otherwise the BufferedOutputStream won't send its output to the socket.

Categories