My SocketServer first listens for at least 4 Socket connections before creating a WorkerThread where all four connections are served. And in the same thread, all 4 sockets will be opened to perform communication with connected clients.
Now, consider a situation where server has already accepted two socket connections, but listening to remaining 2 clients, before it can proceed with creating thread.
And while that listening phase, the connected clients are shown "Waiting..." message (since server has not yet opened the sockets to send any response back to clients, and socket.readObject() is blocking at client-end), till the server gets all 4 clients to work with. And in the meantime, one of the "already-connected" client kills that "Waiting..." thing, and closes the client app. In such a case, my WorkerThread will fire an exception due to dead socket supplied, when it attempts to open it.
How can I know if a socket is pointing to nothing (since client is lost) without having to open the socket? (since if I open it from main thread, I'll not be able to open it again from WorkerThread, where it is actually supposed to be used).
If I get to know if Socket is dead, I can get server back to listening and attempt to get 4 connections, before it proceeds creating a thread.
I know my SocketServer will be stuck at accept() so even if its possible to check what I asked above, I'll have to create another thread that monitors liveliness of already "accepted" socket connections.
Update
I mean by not opening the socket is something like below.
Socket s = ss.accept();
/* I'll not be doing as below, since once I close InputStream and OutputStream in main Thread, I can't open in WorkerThread.
But I still want to know if Socket s is connected to client, before I start WorkerThread.
ObjectInputStream in = new ObjectInputStream(s.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(s.getOutputStream());
String msg = in.readObject().toString();
System.out.println("Client Says:");
out.writeObject("success");
in.close();
out.close();
*/
new WorkerThread(s).start();
And note that my server is accepting 4 such connections, and when 4 sockets are accept()ed, it passes all 4 in WorkerThread's constructor, and gets back to accept() another 4 clients.
I think you just need to handle your acceptions better. You should handle the IOException correctly whenever you try to read or write to the socket.
One option is to have the accepting code send a "still waiting" message to the client and get an acknowledge every so often while you are waiting for the other connections. The socket and associated streams have already been created by the accept() so you can do this, call flush() on the OutputStream, and then hand off to the handler.
As long as you don't call close() on the streams, you should be able to re-use them without a problem. You just can't have two different threads using the streams at the same time.
Related
I'm writing a simple Java server that accepts multiple client socket connections. I'm using a separate thread to handle each client/socket. Considering I have set up the networking including the BufferedReader, InputStreamReader, and FileWriter etc. for this client/socket.
My code is :
//run method of my Runnable everytime a new client connects
public void run(){
String message = null;
while((message = bufferedReader.readLine())!=null){
System.out.println(message+"/n");
//do some other things like writing this message
//to another client or saving it in a file, etc
}
}
Does this keep the client socket open? or does the socket eventually makes the thread goes dead when it's done reading from the stream
Will it keep waiting for more/new messages/data from the client socket even after it's done reading for the first time?
Once the server accept client request, the server is capable of exchanging messages with the client endlessly until the socket is closed with its streams.
To allow continuity in communication, you have to read from the stream inside a while loop and only exit when the client sends a termination request. So in your case the client socket is open until you read, once you exit from the loop your connection will be terminated.
Where did you create the bufferedReader ?
The thread will end when the readLine call returns null. That happens when the reader reaches the "end of stream". If the BufferedReader is wrapping an input stream associated with a socket, then "end of stream" will be triggered by the socket connection closing; e.g. because the remote client / server closed it.
There is no code shown here to close the BufferedReader. It will be closed if either something else calls close on it, or if the BufferedReader object becomes unreachable. In the latter case, the reader and the underlying socket stream and socket will eventually be closed when the GC finalizes the objects.
My question is does this keep the client socket open? Or does the socket and eventually the thread goes dead when it's done reading from the stream, or will it keep waiting for more/new messages/data from the client socket even after it's done reading for the first time?
It depends. See above.
The point is that the code as written reads until there is no more to read. Not until "it is done". Or to put it another way "it is done" ... if and only if the other end tells it so, by closing the stream.
I am trying to write a multi-client socket system which communicates via strings sent by the client, which will trigger an event according to its content.
There is a lot of materialon how to do it, but I cannot grasp the logic behind it.
In this example and enter link description here in this one, there is a while true piece of code which has two main instructions:
socket.accept();
Thread t = new Thread(runnable);
I cannot understand how this works:
the while(true) continuously passed over those instructions, but creates a Thread only when the accept() method clicks?
Does the new thread have a dedicated port? Isn't the socket communication one on one?
How does the software keep track of the spawned socket threads, and does it actually matter?
How do I send a reply to the thread that just wrote me?
Maybe it's my lack of google skills, but I cannot find a good tutorial to do this stuff: help?
the while(true) continuously passed over those instructions, but creates a Thread only when the accept() method clicks?
the execution stop on method accept() until someone try to connect.You can see this using the debug mode on our IDE.
Does the new thread have a dedicated port? Isn't the socket communication one on one?
No, you have many connections on the same port
How does the software keep track of the spawned socket threads, and does it actually matter?
Do bother about this for now
How do I send a reply to the thread that just wrote me?
When someone try to connect you receive an object to respond this user, check the documentation
•the while(true) continuously passed over those instructions, but creates a Thread only when the accept() method clicks?
A new Thread is created to listen for data coming in through the Socket (see Socket.getInputStream())
•Does the new thread have a dedicated port? Isn't the socket communication one on one?
Threads do not have ports. But the Socket has a dedicated address for communicating with this client
•How does the software keep track of the spawned socket threads, and does it actually matter?
That depends on the software. But most of the time, you would keep a record of connected Sockets in some sort of Collection - A List perhaps, or a Map between the userID and the Socket if clients are logging in.
•How do I send a reply to the thread that just wrote me?
In a simple sense, it's as simple as
ServerSocket ss = ...;
Socket s = ss.accept();
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println("Hello World");
You need to make sure that your PrintStream doesn't then get Garbage Collected, as this will close the Stream / Socket
I am trying to write code to hot-swap sockets in Java.
Here is the gist of the code I am currently using:
// initial server initialization
ServerSocket server1 = new ServerSocket(port);
// ... code to accept and process requests
// new server initialization
ServerSocket server2 = new ServerSocket();
// attempt at hotswap
server1.close();
server2.bind(port);
// .. more code
The code works as above but I am wondering about the possibility of dropped messages between the time the first socket is closed and the second one is opened.
Two questions:
Is there a way to ensure that no connections are dropped?
If there is a way to ensure that no connections are dropped does it still work if the instances of the ServerSocket class are in different virtual machines?
Thanks in advance.
The closing of a ServerSocket means that that server1's handler does not handle new incoming connections, these are taken care of by the server2. So far so good. You can garbage collect server1 when it no longer has any connected Sockets left.
There will be a (shorter or longer) period of time where the port is marked as "not open" in the OS networking driver after the first ServerSocket is closed and the second one is opened (since the OS cannot know our intention to start a new socket directly after closing the first one).
An incoming TCP request during this time will get a message back from the OS that the port is not open, and will likely not retry, since it got a confirmation that the port was not open.
A Possible work-around
Use the java NIO constructs, which spawn a new thread per incoming request, see the ServerSocketChannel and be sure to check out the library http://netty.io/ which have several constructs for this.
Make sure that you can set the handler for the incoming request dynamically (and thread safe :), this will make it possible to seamlessly change the handling of the incoming requests, but you will not be able to exchange the ServerSocket (but that's likely not exactly what you want, either).
I have a client that will connect to a server through a socket. After connecting every event that happens on the server will be sent to all registered clients.
Every client should receive data related to the event.
I just need to implement the client...meaning I need to connect to the server and receive the events' data.
I was thinking on doing something like:
this.socket = new Socket(InetAddress.getByName(host),
this.socket.connect(socket.getLocalSocketAddress(), SOCKET_TIMEOUT);
And then launch a thread which gets the InputStream of the socket in a while loop.
But I don't know if this the best way to implement an event driven client through a socket.
Is it?
In an event driven environment a Datagram Socket will incur lower network overhead but will not give you the reliability. Here is a tutorial about writing datagram socket clients and servers.
This is often done by spawning a separate thread for the client that continuously makes blocking calls to read() from the stream - that way, as soon as data becomes available the read() call unblocks and can act on what it received ('the event fires'), then it goes back to blocking waiting for the next event.
You don't necessarily need a thread here unless the client has to respond to some other input like GUI events.
Then, assuming you are talking about TCP, read from the socket in a loop, buffering received data until you have a complete application "event", and call your application "event handler". It's that simple.
I have a thread for each connection on the server-side. When the client is not sending commands, the server thread is blocking:
while ((commandHeader = fromNode.readLine()) != null) {
which internally calls readLine() on an OutputStream obtained from the TCP socket.
When I call socket.close() from another thread, this calls wakes up with a SocketException and the thread can be terminated.
However, if a client than wakes up and decide to issue a command, it executes
stream.writeBytes("something\n");
which blocks indefinitely. I understand this is probably fine for TCP (it's just an half-close.)
I should probably send something to the client upon quitting, like "QUIT\n"; it could also just read an EOF. But if I call readLine() or other read operations on the client before sending the command, they block waiting for data when the connection is not closed.
How can the client detect that the connection has been half-closed before trying to write to it?
When socket.close() is called on server the underlying TCP connection is closed with the typical FIN/FIN-ACK sequence plus RST packets, so the client will know. When the client calls stream.writeBytes() afterwards it should fail. If it doesn't it means there has been some missing packets and the connection eventually will fail anyhow.
First i think your application logic should be such that to avoid Half Open TCP connection. You can think of adding timer on client side so that if nothing received it starts polling the server again.
From server point of view, another option is to set timer on the readLine. Make another method for readLine where you set a timer and if it excedes certain time, simply return some default value to the while loop.
EDIT:
You might want to read this article specially the section: What about threads blocked on IO?