Something to know about socket and multithreading in java - java

I want to send a message to a socket on a gateway(client), and then wait for a message to recieve from a gateway.
While waiting, on other hand I again send a message from server socket to gateway which is client but on accept()(ServerSocket) method my connection blocks.
I was wondering is this because of the previous request which was waiting to recieve something by using inputStream. I used threads to maintain this and use setReuseAddress() to do this.
I am not posting a code right now as I just want to know is this logic is fine or is there any logic to handle multiple requests(messages) to be send from a Server-Socket to a client-Socket and I also dont want to close the socket because the socket has to be connected through out the application.

On the client end, you use a Socket object to connect to a server which uses a single ServerSocket. Once the connection is established you will have a Socket at both ends and you can use this Socket to Serversocket connection to send data in either direction. i.e.
A single server socket is needed for new connections only.
See: here

Related

What's happening when server.accept()

I'm trying to write a simple Java chat application in Server/Client.
I'm confusing in below method at server.accept() :
private void waitForConnection() throws IOException {
showMessage("Waiting for someone to connect... \n");
// `connection` is an instance of `java.net.Socket`
// `server` is an instance of `java.net.ServerSocket`
connection = server.accept();
showMessage("Now connected to " + connection.getInetAddress().getHostName());
}
Please tell me connection is equal to what?
And also server.accept() returns what?
Any helps would be awesome.
Assuming your server variable is a java.net.ServerSocket then the accept() method returns a java.net.Socket object.
From the returned Socket object, you have access to both the InputStream and OutputStream to read from and write to the connected client.
Your program should halt until a client connects. That's what the line connection = server.accept(); does. Returning type is a type of Socket, too.
That's the "connection" to your client, you can read from and write to.
Check this and that site to read more about network programming in Java.
when you do connections between two systems then you require a socket.
Socket of one system is connected with socket of another system. Both these sockets are connected via I/O stream. you can write to this stream and can read from this stream.
One system serves as server and another system serves as client .
As socket is combination of port no. and IP so server open its port no. and client try to connect with the server's IP and port no.
For connection to be maid the server accepts the incoming socket using accept() function. accept() function returns a local socket which is connected to another socket at the client..
accept() waits until a client socket arrives.

Sending both data and ACKs from the same port on the same machine

I am implementing the TFTP (trivial FTP) protocol in Java. I have a client and a server, and so far the client can request a file and the server sends him that data.
Here is where I hit my problem - for obvious testing reasons, I run both the client and the server on my machine. However, when sending a file, there have to be two sockets listening on the same port:
the client needs to listen for received data packages
the server needs to listen for the client's acknowledgements
...and also two respective sockets for sending data and acknowledgements, also sharing a port.
This normally does happen on the same port, but on different machines. Is there a way to get around this, and make both client and server work peacefully on the same host, without any ugly hacks? And by ugly hacks I mean something like:
predefined offset for the ACK communication port (such as +15 over the data port; this is what I'm currently using now. It sort of works but it feels wrong and is error-prone)
repeatedly closing and opening sockets (send data, close socket used to send data so that the client can use that port to send his ACK, etc.); this also works at the moment, but also via a hack. Here is, for example, how I "reopen" a socket used for sending things:
public void open() {
try {
socket = new DatagramSocket(localPortCache);
} catch (SocketException e) {
e.printStackTrace();
}
}
This is evil. My sockets, originally, receive dynamically-allocated ephemeral port numbers. I then memorize that value and use it to "restore" my socket to the old port. However, it can't be guaranteed that that port is still available. It usually is, but there's no guarantee. Am I being overly-paranoid in this case?
generating a new ACK-communication port in the handshake and send it to the client via the control port (69) in an additional step
Update:
I have managed to fix my problem. My issue was that I wasn't trying to reuse my sockets. For instance, I sent something from a socket on port X, but then tried to allocate a new socket on that port to listen for the ACK, instead of just reusing the old socket.
The client doesn't need to use a fixed port number. Just bind it to zero. The server should send the response back to the originating client whatever its port number.

Chat server writing to closed sockets

Essentially I have a server class and a client class, the client creates a socket and sends whatever you type into the server, which gets written to the output streams of a vector of sockets from all the existing clients. It works well except when you close a chat client, after which the next message sent gives the following exception:
java.net.SocketException: Software caused connection abort: socket write error
I think what's happening is that the socket closed by the client is either not closing the socket in the server's vector of sockets, or that even when it's closed, it remains in the vector and then tries to write to a closed socket. Does this sound like what might be happening? I don't understand exactly what the socket.close() method does regarding the socket it's connected to.
You close the socket on the client side, but on the server side it is not closed and this is why you get this exception.
In a graceful close you should send a CLOSE message from your client which will close the socket on the server side.
If a socket on the client was closed then you must handle your exception on the server side e.g. by removing it from your vector of sockets.
If the client closes his socket you will read EOS at the server (read() returns -1, readLine() returns null,readXXX() throws EOFException for any other X), or get an IOException: connection reset by peer when writing, probably not on the first write. If either of these things happens you must close the socket in the server and forget about that client in all ways.
I don't think it's like both sides of connection are holding together by hands, and if you split them they always will feel it. Check if socket is closed before sending and catch exceptions to solve this problem.

send a string to a specific client on LAN network [duplicate]

I have two wifi modules M1 and M2 that connect to my access point. I have an android phone that connects to the same access point. I have a socket server on my android phone and the two modules join to the server as clients. Now my question is, is it possible to send a string message from my phone to module M1 without having to send anything to M2. I want to choose between clients to send the message to. Is it even possible in Java?
Ok, here goes.
//setting up server
ServerSocket serverSocket = new ServerSocket(8000, 0, IPaddress);
//creating a client socket to accept it
Socket clientSocket = serverSocket.accept();
Now, I accept the client in a seperate thread so that the main thread does not freeze becauz accept() function is blocking.
I don't know how to create a new thread every time a new client connects. Also I dont know how to limit the number of clients that can connect. I need at most 5 clients and no more.
Yes, it is possible. You need to maintain a separate connection to each client. The ServerSocket class has an accept() function which returns a Socket object. That object represents a connection between two points, your server and one client. You can call ServerSocket.accept() multiple times in a loop to accept all incoming connections. Each Socket object returned will be for a different client.
In order to have the server send a message to a specific client, it will need to know which socket belongs to which client, so the clients will have to send some message to the server identifying themselves, and the server will need to read and interpret that message. Then it can respond with the appropriate response for that specific client.
Post your code if you are still having trouble.
UPDATE because you added code to the question: See the Android Documentation about creating threads. That will be a lot of reading beyond this post on stackoverflow.
As to accepting connections and starting threads, just do it in a loop:
for(int i = 0; i<5; i++){
clientSocket = serverSocket.accept();
// start a new thread, passing it the clientSocket as an argument
}
Other possibly useful links:
https://developer.android.com/resources/articles/painless-threading.html
https://developer.android.com/guide/topics/fundamentals/processes-and-threads.html

How can I force the server socket to re-accept a request from a client?

For those who do not want to read a long question here is a short version:
A server has an opened socket for a client. The server gets a request to open a socket from
the same client-IP and client-port. I want to fore the server not to refuse such a request but to close the old socket and open a new one. How can I do ti?
And here is a long (original) question:
I have the following situation. There is an established connection between a server and client. Then an external software (Bonjour) says to my client the it does not see the server in the local network. Well, client does nothing about that because of the following reasons:
If Bonjour does not see the server it does not necessarily means that client cannot see the server.
Even if the client trusts the Bonjour and close the socket it does not improve the situation ("to have no open socket" is worser that "to have a potentially bad socket").
So, client do nothing if server becomes invisible to Bonjour. But than the server re-appears in the Bonjour and Bonjour notify the client about that. In this situation the following situations are possible:
The server reappears on a new IP address. So, the client needs to open a new socket to be able to communicate with the server.
The server reappears on the old IP address. In this case we have two subcases:
2.1. The server was restarted (switched off and then switched on). So, it does not remember the old socket (which is still used by the client). So, client needs to close the old socket and open a new one (on the same server-IP address and the same server-port).
2.2. We had a temporal network problem and the server was running the whole time. So, the old socket is still available for the use. In this case the client does not really need to close the old socket and reopen a new one.
But to simplify my life I decide to close and reopen the socket on the client side in any case (in spite on the fact that it is not really needed in the last described situation).
But I can have problems with that solution. If I close the socket on the client side and than try to reopen a socket from the same client-IP and client-port, server will not accept the call for a new socket. The server will think that such a socket already exists.
Can I write the server in such a way, that it does not refuse such calls. For example, if it (the server) sees that a client send a request for a socket from the same client-IP and client-port, it (server) close the available socket, associated with this client-IP and client-port and than it reopens a new socket.
You can't "reopen" a socket on your server. If the socket already exists and the client is trying to reconnect then you should get an BindException (see your previous question). The scenario that may be possible:
Client Shuts down socket
Server OS "notices" socket is dead on client side and shuts its side down
Client reconnects on the same port, but with a "new" socket
In this case you may consider it be the "same" socket, but it really isn't. That said a strategy you may wish to adopt is to have some sort of map (hash of client IP/port) to whatever mechanism you are using to service the socket or some kind of persistent state data, so that it can simulate a continuation of a previous socket (in the same vein as http sessioning). Something along the lines of:
HashMap<Client, State> sessions = ...;
public void server(){
...
while(true){
Socket socket = server.accept();
Client client = new Client(socket);
State s = sessions.get(client);
if(s == null){
s = new State();
sessions.put(client, s);
}
client.setState(s);
service(client);
}
...
}
and you can adjust the map lookup to define what a "session" means within your application (same client IP, same client IP & client port, some sessionid sent over the wire, etc).
If you are just trying to make it possible for the client to reconnect and force the server to "notice" the client is disconnected, the only real way in Java is to try and read/write data, and if it has been shutdown then it should throw an exception. Therefore as was mentioned in your other question you could add some kind of ack/nak feature to your protocol and add some type of check if you believe the client is disconnected (for example if you haven't read any data in the last N milliseconds, send a message the client must echo within M milliseconds, otherwise it is assumed to be disconnected). You can also try isConnected, isInputShutdown, isOutputShutdown, but I have found those to be unreliable in my own code to indicate the socket state, unless you have closed the socket (i.e. the one you are testing on the server).
The situation you describe is impossible. You can't get a new connect request from the same remote IP:port as an existing connection. The client will not permit it to occur.
Based on the comments:
You cannot write the server in a way that it will close a socket it still thinks is connected and automatically accept the new connection, as application code does not have that kind of control over the TCP stack, nor is there a way to reopen a connection.
The chance of the port numbers being the same between your client restarts is very small.
But still, if that happens, the server will note that that you're trying to set up an already connected socket, and refuse your new connection. There's not much else your client can do in this case besides close your socket, create a new one and try to connect again - and another random port will be selected.
additional note, your server should take some form of action to detect and close dead sockets, if all your server does is read incoming data, the "dead" sockets will never be
closed as they will never be detected as dead.(enabling tcp keepalive is one cheap measure to take against dead sockets staying up for months, though it will take a couple of hours to detect them as such by default.)

Categories