I want to connect a client to many servers and receive the first answer from one of them. So I decided to use select. I created a socket with each server and I registered those sockets in a selector. But it didn't work. Here's where there is a problem in my code:
Selector selector = Selector.open();//
int i;
for(i=0;i<serveurs.size();i++)//I have an arraylist of servers
{
Socket s=new Socket(serveurs.get(i).getIP(),port);//creating a socket with the server number i
sc=s.getChannel();//here's the problem: sc is null
sc.configureBlocking(false);//exception here because sc=null
sc.register(selector, SelectionKey.OP_READ);//register the socket channel to recieve data form the server
}
selector.select();
// reading data in the socket registered in the selector
So what can I do to solve this problem ?
Refreshing the book "TCP/IP Sockets in Java, 2nd Edition" came across playing with time server and client. The small demo code for TcpTimeClient.java basically does what you described.
Problems I can see in your code:
To get a SocketChannel, use SocketChannel.open(). The JavaDoc of Socket.getChannel() tells what to do.
Use interest OP_CONNECT to try all connections first, then use interest OP_READ to find the winner.
Concerns depending on the application protocol:
Avoid deadlock, e.g. if server expects reading a message from client before responding and client just waits for response without writing the message first.
The first winner might not be the best, consider any other QoS approaches. Or keep all connections open and switch if necessary.
Related
This question already has answers here:
Java socket API: How to tell if a connection has been closed?
(9 answers)
Closed 2 years ago.
So I'm in the making of a very simple server/client complex using java. So far I have managed to figure out what happens if the client quits, because then the server receives null while listening from any input from the client.
BUT - what happens if the client is connected and the server quits for any reason... the server is supposed to wait for input from the client, but how can the client know that the server is not listening anymore? For me the clients call to the server just goes into the void... nothing happens...
Can I do something to find out when the server goes down? Time-out, ping/pong or something?
As You surely can see I'm quite new at this, I'm just curious. This was a puzzle for me ever since I attended computer science at the university.
Thanks in advance. dr_xemacs.
(I am assuming you are working with blocking server socket and socket and not with non blocking ones)
Similarly to the server, reading from streams of a closed connection will return null.
However if you instead do not want to rely on this or a scared that the connection to the server could somehow persist, you can also use time outs (check this out! ) which will throw SocketTimeoutException when the time is up and, to keep track of whether the server is up or not, create a ping/packet to assure server is still up and running.
Edit: I did a quick search and this could be useful to you! Take a look!
How can the client know that the server is not listening anymore?
If the client doesn't attempt to interact at some level with the service, it won't know.
Assuming that the client has sent a request, a few different scenarios.
If the service is no longer listening on the designated port, the client will typically get a "Connection Refused" exception.
If the service is still running (in a sense) but it is not working properly, then connection attempts from the client are likely to time out.
If the service's host is down, the client liable get a timeout.
If there are network connectivity or firewall issues, the client could get a timeout or some other exception.
Can I do something to find out when the server goes down? Time-out, ping/pong or something?
You attempt to connect and send a request. If it fails or times out, that means the service is down. If you are designing and implementing the service yourself, you could include a special "healthcheck" request for clients to "ping" on. But the flip-side is that network and server resources will be consumed in receiving and responding to these requests. It can affect your ability to scale up the number of clients, for example, if each client pings the service every N seconds.
But a client typically doesn't need to know whether the service is up or down. It typically only cares that service responds when it it sends a real request. And the simplest way to handle that is to just send the request and deal with the outcome. (The client code has to deal with all possible outcomes anyway when doing a real request. The service can go down, etc between the last healthcheck ping and when the client sends a real request.)
Bottom line: Don't bother with checking availability in the client unless the application (i.e. the end user) really needs to know.
Your Server probably may be running on a certain port and so you can add a health check at the client side and update a global flag with status to let client know about its availibity :-
Socket socket = null;
try
{
socket = new Socket(host, port);
return true;
}
catch (Exception e)
{
return false;
}
finally
{
if(socket != null)
try
{
socket.close();
}
catch(Exception e){}
}
Take it easy with me, I'm new in socket programming.
I'm about making a program which is similar to Teamviewer. I could make a simple Server/client application which is multithreaded. But the problem is I couldn't figure out how to do something like :
Let's say I have Server and a client connected to server.
I could transfer a file from client to server. I could make a simple chat with a client. But my problem is : How can I chat with the client while file is transferring in the same time? I mean I couldn't make more than one function in a time.Because we have just one input and one output for both server and client. So how could I send more that one function to client and how could the client read more that one function in a time and respond to requests ?
I did something like : I sent a request to client and I got the response in a new thread which contains a new DataInputStream but I couldn't figure out how the main DataInputStream will receive a new response from the client because what is receiving the requests in this way is the new DataInputStream. I'm really lost in this situation because I feel my concept is completely wrong but I couldn't figure out the right concept to do something like that.
Is it possible with ServerSocket or should I look at NIO Socket ?
NOTE :
I don't want a piece of code, I would like to understand the concept of the whole operation for something like that. Thank you
Use a packet based massaging system over a single connection
Outgoing
{"type":"chat", "message":"hi"}
{"type":"xfer", "fileName":"fileX", "data":"some_binary_data"}
Incoming
switch(getString("type")){
case "chat":
System.out.println("User said" + getString("message"));
break;
case "xfer":
File f = new File(getString("fileName"));
f.write(getString("data"));
break;
...
}
Obviously if the binary file is fairly large, you should break it into many different messages and reassemble it on the other side, this would allow chat messages to make their way across the wire while the transfer is also still taking place.
My app can transfer files and messages between server and client. Server is multithreaded and clients simply connects to it. While file is being transferred, if sender sends a message, it will be consumed as bytes of file.
I don't want to open more ports,
Can I establish a new connection to the server for file transfer? Or I
should open a separate port for files.
I don't want to block communication while a file is being transferred.
The question was marked as a duplicate but its not, i am trying to send messages and files simultaneously not one by one. I can already receive files one by one. Read again.
Also, as server is multithreaded, I cannot call server socket.accept() again to receive files in new connection because main thread listening for incoming will try to handle it instead. Is there a way around?
Seems to me like trying to multiplex files and messages onto the same socket stream is an XYProblem.
I am not an expert on this, but it sounds like you should do some reading on "ports vs sockets". My understanding is that ip:port is the address of the listening service. Once a client connects, the server will open a socket to actually do the communication.
The trick is that every time a client connects, spawn a new thread (on a new socket) to handle the request. This instantly frees up the main thread to go back to listening for new connections. Your file transfer and your messages can come into the same port, but each new request will get its own socket and its own server thread --> no collision!
See this question for a java implementation:
Multithreading Socket communication Client/Server
you could use some system of all the lines of a file start with a string like this (file:linenum) and then on the other side it puts that in a file then to send text you could do the same thing but with a tag like (text)
Server:
Scanner in = new Scanner(s.getInputStream());
while(true) {
String message = in.nextLine();
if(message.length > 14 && message.substring(0,6).equalsIgnoreCase("(file:") {
int line = Integer.valueOf(message.substring(6).replaceall(")", ""));
saveToFile(message.substring(6).replaceAll(")","").replaceAll("<1-9>",""));
} else {
System.out.println(message);
}
}
I think that code works but I haven't checked it so it might need some slight modifications
You could introduce a handshake protocol where clients can state who they are (probably happening already) and what they want from the given connection. The first connection they make could be about control, and perhaps the messages, and remain in use all the time. File transfer could happen via secondary connections, which may come and go during a session. Having several parallel connections between a client and a server is completely normal, that is what #MikeOunsworth was explaining too.
A shortcut you can take is issuing short-living, one-time tokens which clients can present when opening the secondary connection and then the server will immediately know which file it should start sending. Note that this approach easily can raise various security (if token encodes actual request data) and/or scalability issues (if token is something completely random and has to be looked up in some table).
I am trying to build an Android IM, since users may have new messages from others, should I keeps the TCP connection open and keep reading data from it? e.g.
while(!shutdown) {
int count = socketChannel.read(buffer);
// do something with buffer
}
This depends on your implementation. If you're using blocked sockets then you wouldn't want to do this. It would mean that if you have more than one client connecting to the server they would block all other clients from connecting to that server socket.
What you could do is have a server socket running consistently (as you normally would) and then to connect to it with a client socket to check and receive any new messages that have arrived. Once you've received your message you can close the socket. This could be performed every n seconds.
The other option is to use non-blocked socket connections and always keep them open but this could lead to issues if you have many clients.
Kindly find in the details of assignment:
Start a TCP Server.
Start multiple clients to connect to the server.
On connect :
Server gives each connection a random unique name
Server starts sending PING messages to client as : “PING client abc123 at time hhmmss” every 5 seconds.
Client receives the PING messages and prints them to console.
On connect :
Client starts sending “Time request” messages every 10 seconds
Server gets the message and responds : “Client abc123, the time is hhmmss”
Client gets the time messages and prints them to console.
Things to note :
Use plain sockets (not NIO)
Make sure that the socket handling code is reusable
Make sure that the time request reads and writes are asynchronous.
Ensure that ping and all other reads and writes are also asynchronous
Ensure that ping and time response messages do not intersperse or corrupt each other
We are not here to write a program for you, but here is some stuff you can use to solve most of the problems in your project.
First off you are using TCP in Java so you will be using the following objects:
Socket - Client connection
ServerSocket - Server host
There is documentation on how to use these here.
Server side, you want multiple connections and you will want the rest of the program to run. This means multitasking. The ServerSocket should run on a separate thread. Then it should be put in a do-while loop to accept() connections. The server will then wait there until a client socket connects. When a connection is made you will need to create a new thread to let the ServerSocket accept more clients. Make sure when multi threading to use synchronized methods.
Create ServerSocket like this: new ServerSocket(port); This will open server on int port.
On the client side we will also use multithreading. The Socket will need to be on a seprate thread and to create a Socket to connect to an ip and port do the following: new Socket(ip, port) (ip is a String)
Once connected both the server and client will need to communicate. An easy way to do this is to send a message back and forth. You can't just not send because the server or client will pause and wait on receive and not be able to send. I will get to this issue in a minute.
One way to send would be to use a PrintWriter. Create a new PrintWriter with the Socket output stream. From here you can send by printing line with PrintWriter.
Make sure you flush or autoFlush your PrintWriter or else it will keep sending the same message over and over.
You can then receive a message by using BufferedReader by creating a new InputStreamReader from the socket input stream. Doing this you can use readLine(). Remember this will pause until something is received.
Doing this on both the server and client you can send back and forth. Once at this point you could easily do the rest of your requested assignment.
As I mentioned earlier, this method will result in the server and clients sending and receiving over and over even if the message is empty. Doing the following can prevent this and use less cpu and bandwidth as it will only send when it has a message to send:
(I created this diagram for a forum post for a project update I have created once)
The green lines represent received data going somewhere and the red represent data from the program going to the sender thread to be sent.
Notice on this diagram that there is a thread for receiving and sending. This allows one to send messages while the other receives, so the sender won't pause if the receiver does pause to wait to receive a message.
Other good resources:
Simple Chat Program
enter link description here