I am currently working on a server-client communication. On server-side, I have a Thread listening continuously for any incoming data from the client.
while ((foo = (Foo) objectInputSteam.readObject()) != null) {...}
Sometimes I also need to send data from the server to the client. (Not as a direct response.) After sending some data to the client over the same socket, an exception will be thrown once new data reaches the server (0xAC).
As far as I know, this happens because the inputreader is reading while sending data over the same socket.
Is there any way to interrupt the listening thread while sending the data to the client or do I need to create a second socket on a different port for outgoing traffic?
Related
I created application in android studio and server in python and I want to connect the client to my server with one socket per client so that I don't need to close the socket and I could send data from the server to any connected client I want.
My server is multi-threaded and it working only if I'm closing every socket after sending data back.
At my java app I created class that contain socket object and methods to contact with the server and I think that my problem is at this method:
private static String getMessageFromServer() throws IOException {
in = new InputStreamReader(sock.getInputStream());
bf = new BufferedReader(in);
return bf.readLine();
}
As you can see this method reads data from the server and the problem is that it keep reading data until the server close the socket, so I'm asking if there is any option to read data from server and stop the reading after I already got the data and without the server closes the socket?
Thanks :-)
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
I have following Socket server's code that reads stream from connected Socket.
try
{
ObjectInputStream in = new ObjectInputStream(client.getInputStream());
int count = 10;
while(count>0)
{
String msg = in.readObject().toString(); //Stucks here if this client is lost.
System.out.println("Client Says : "+msg);
count--;
}
in.close();
client.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
And I have a Client program, that connects with this server, sends some string every second for 10 times, and server reads from the socket for 10 times and prints the message, but if in between I kill the Client program, the Server freezes in between instead of throwing any exception or anything.
How can I detect this freeze condition? and make this loop iterate infinitely and print whatever client sends until connection is active and stable?
The problem is that the server side of the socket has no way of knowing that the client connection closed because the client code terminates without calling .close() on the client side of the socket, and therefore never sends the TCP FIN signal.
One possible way of fixing this would be to create a new Watcher thread that just periodically inspects the socket to see if it is still active. The problem with that approach is that the isConnected() on the Socket will not work for the same reason stated above so the only real way to inspect the connection is to attempt to write to it. However, this may cause random garbage to be sent to a potentially listening client.
Other options would be to implement some type of keep-alive protocol that the client should agree to (i.e., send keep-alive bits every so often so the Watcher has something to look for). You could also just move to the java.nio approach, which I believe does a better job at dealing with these conditions.
This thread is old, but provides more detail: http://www.velocityreviews.com/forums/t541628-sockets-checking-for-dropped-connections-and-close.html.