I've written a java intake program that send an PDF-formatted intake to a shared folder so that other people in the network can read it. However, there is not a way for the other people to know that an intake was sent unless someone tells them, so I want the program to send an alert message to the other computers telling them that an intake has been sent.
Now I've done some research into this and figured that TCP is the way to go since it's reliable. I also know that this is a one-to-many sending going on, so I assume that my Intake program will act as the server an the other computers will be the client, or should it be the other way around?
Now I assume that I have to create a client program that listens to the server and waits for it to send a message.
With that in mind, how do I:
Create a client program that listens for the message continuously until the program is closed. I assume that I'll be using "while (true)" and sleep. If so, how long do I put the program to sleep?
Make it as part of Windows service so that can load up when Windows start.
On the server end, how do I:
Send messages to more than one computer, since TCP is not capable of multicasting or broadcasting. I assume an array/vector will play a part here.
Oh, this is a one-way communication. The client doesn't have to respond back to the server.
First of all, UDP is quite reliable (in fact, as reliable as the IP protocol itself). TCP simply ensures that the data was received which involved quite a lot of magic in the back end. Unless you absolutely need to be sure that other machines got the message, you could do it with UDP. Mind that I'm not saying “Don't use TCP”, I just want to make it straight that you should take UDP into consideration as well.
Anyway, yes, you can create a simple listening program. Here is an example of a client in Java that reads messages from the server. It overrides the run method of a Thread class:
public void run() {
try {
String messageFromServer = reader.readLine();
while (messageFromServer != null) {
// Do things with messageFromServer here
// processor.processFromServer(messageFromServer);
messageFromServer = reader.readLine(); // Blocks the loop, waits for message
}
}
catch (IOException e) {
// Handle your exception
}
}
Amongst other things, my thread was set up as such:
public CommunicationThread(String hostname, int port, int timeout) throws IOException, SocketTimeoutException {
InetSocketAddress address = new InetSocketAddress(hostname, port);
socket = new Socket();
socket.connect(address, 2000); // 2000ms time out
// You can use the writer to write messages back out to the server
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
Now, regards to server-side you can do something as follows:
Write a program to allow clients to contact, given that they know your address.
Accept the connections, and store the sockets in a list.
When you need to send out a message, traverse the list and send the data to everyone on it.
You can start listening on your server with
this.socket = new ServerSocket(port);
You could (or even should(?)) make it threaded so that you can accept clients while serving others. You can accept new clients with:
socket.accept(); // Blocks, waiting for someone to connect, returns open socket
Feel free to pass that to a whole new class which can deal with BufferedWriter (and maybe even BufferedReader if you want to read from clients as well). That class is where you would implement things such as writeToClient(message)
Consider the situation where you have a ClientConnection class that has writeToClient(String s) method and (Server server, Socket socket) and initialized ArrayList conList.
Here is how you would follow:
In a separate thread in Server, accept connections with
ClientConnection con = new ClientConnection(this, socket.accept());
conList.add(con);
Then, when you want to write to clients:
for (ClientConnection c : conList) {
c.writeToClient("I'm sending you a message!");
}
I hope you get a vague idea of what you need to do. Read the Socket documentation, it's very useful. Also, as always with threaded applications, make sure you aren't doing things such as modifying a list while traversing it and avoid race conditions.
Good luck!
Related
I'm making a simple UDP chat program, and i would like the server to be able to send to the client without receiving data from it first. Normally, when it receives data from the client, the server gets the IP and port of the client, so it can communicate with it.
My server code:
package com.ageforce;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class ChatServer {
DatagramSocket server;
byte[] receivedData = new byte[1024];
Scanner scanner = new Scanner(System.in);
byte[] sentData;
DatagramPacket dp2 = new DatagramPacket(receivedData, receivedData.length);
public ChatServer() throws SocketException {
server = new DatagramSocket(7000);
}
public static void main(String[] args) throws SocketException {
ChatServer cs = new ChatServer();
Thread receiveMessage = new Thread(() -> {
while (true) {
try {
cs.server.receive(cs.dp2);
} catch (IOException e) {
e.printStackTrace();
}
String storedData = new String(cs.dp2.getData());
System.out.println(storedData);
}
});
Thread sendMessage = new Thread(() -> {
while (true) {
String sentMessage = cs.scanner.nextLine();
cs.sentData = sentMessage.getBytes();
// This is the area of the code where the server gets IP and port of client from the received data. I'd like this to be changed.
InetAddress getIP = cs.dp2.getAddress();
int port = cs.dp2.getPort();
DatagramPacket dp3 = new DatagramPacket(cs.sentData, cs.sentData.length, getIP, port);
try {
cs.server.send(dp3);
} catch (IOException e) {
e.printStackTrace();
}
}
});
sendMessage.start();
receiveMessage.start();
}
}
Is it possible to do this? Any reply is greatly appreciated.
How do i get the port and address of client without receiving data from it first?
UDP does not afford that possibility. It is a connectionless protocol, so the server doesn't even know that there is a client until it receives a message from it.
You could conceivably create some kind of preliminary application-level protocol whereby the client announces itself to the server before sending it any chat data, but nothing of the sort is part of UDP itself, and if that's something you want then you should consider using TCP instead, which does have a built-in concept of establishing a connection before sending any data.
In order to send an UDP message to something, you need to know the IP and port number to send it to. How? Well, you tell me.
The way your protocol works right now is that the clients know your hostname (which they let their system turn into an IP automatically), and the port number is hardcoded in the client app. The server knows which IP and port to send data back to by checking the 'sender' IP/port when it receives a call.
If you don't like your current protocol you'll need to figure out a different way to answer this question.
Even if you find a way, you'll find that this is mostly useless. The vast majority of end-users intentionally do not have a so-called publically routable IP address. You cannot reach them by design. In your current protocol, that IP/port combo you send back to isn't really the sending computer at all. It's some router, for example the router in their home. That router saw the outgoing UDP packet and is remembering for a while: Any traffic coming in on that port is supposed to go to that computer in this house.
Short of completely crazy stuff such as 'hole punching' (which skype used for a while, not sure if they still do, it's a complicated hack that doesn't always work and is surely not what you want here - you can search the web for that term), there's simply nothing you can do here. end-user systems aren't servers and cannot be reached like this.
Your run-of-the-mill chat apps will always have clients ping the server and then just keep that connection open as long as they can.
I'm in the process of writing a messaging program, and I'm running into a spot where I'm having trouble understanding how to pass a socket over to a new thread for handling outbound messages via TCP. I'm currently using UDP packets for messages coming from a client, to the server, which, being UDP, doesn't require very much processing, as it's simply listening for incoming packets, before it de-serializes the objects, and processes them as needed in a separate thread. My problem now is, I'm setting up a client initiated TCP socket for reverse traffic, from the server to the assorted clients that connect. I've done a bit of research, and I already understood that each client should have their own thread for handling outgoing messages, along with another thread simply for accepting the incoming connections. I'm unsure of how to actually achieve this, and I've done some research into the topic.
I've found this: http://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html
The resource above basically verified my original suspicion that this would have to be handled by threads dedicated to the client. They included psuedo code here, which is representing my listener thread.
while (true) {
accept a connection;
create a thread to deal with the client;
}
I'm a bit of a visual learner, and I have been searching for some type of an example where this is done. I'm unsure of what variable I'd be passing over to the thread that keeps the original connection open, and pushes data back to clients. I'm also having a little bit of trouble grasping whether it even keeps the same socket open, or if a new one needs to be established, which then, makes me believe a firewall could interfere, but I know that won't be the case.
Can somebody explain this for me in detail? If possible, an example would be greatly appreciated!
I'll be likely replying and commenting on responses in about 15-30 minutes from the time this is posted.
What you are doing sounds correct. I typically implement a server like this (simplified version with no tracking of the clients and so on):
#Override
public void run() {
//start listening on the port
try {
serverSocket = new ServerSocket(port);
logger.info("Listening for connections on port " + port);
} catch (IOException e) {
logger.error("Cannot start SocketListener on port " + port + ". Stopping.", e);
return;
}
while (!stopped) {
try {
//wait for connection
Socket newSocket = serverSocket.accept();
ClientThread client = new ClientThread(newSocket);
Thread clientThread = new Thread(client, MEANINGFUL_THREAD_ID);
clientThread.start();
} catch ...
}
}
where serverSocket is a ServerSocket instance variable and stopped is a flag I use to stop the listener thread.
So to answer your questions in the comment, you normally pass the Socket object to each client thread so that that thread can work with the input and output stream and handle closing of the socket and so on. Once you "accept" a socket connection, you do not need to recreate the ServerSocket, you simply call .accept() again to start waiting for a new connection.
In most cases, you will need to keep track of all client threads in your server so that you can stop the server gracefully or do broadcasts for example.
I would like to have this setup:
Server hosting TCP socket server
Multiple clients connected over TCP (keeping connection open)
Then I would like to initiate a message from the Server to the client. I can't figure out how to do this, and have multiple client sessions at the same time. Techniques I've read involve the Server listening on a port, and when it receives communicate from a client, it launches a new thread to handle and process that, and then it goes back to listening on the port for the next request of another client.
So, then how would I tap into that and send a message to a client running on one of those threads?
My actual usage scenario if you are interested is below. Final goal is like a remote control for your file system to upload files to the server.
- Each client has a java background application running in the system tray that connects to the server
- Server hosts connections, and also hosts a RESTFul webservice to initiate communication
- Mobile device connects to Server over RESTFul webservices to request informatino about the client's filesystem. So it can drill down and find a file, then click and have the file uploaded to the server.
The idea here is mobile users needing to upload files from their desktop to the server while away from their office on a mobile device. (and this is for custom product, so can't use a third-party app_
PS: I've been looking at the simple Client-Server chat program here: http://way2java.com/networking/chat-program-two-way-communication/
You want to have a server listening at all times on a specified port. Once the server notices an incoming connection on that port you should create a new Thread to handle the communication between that client and the server, while the main thread keeps on listening for other incoming connections. This way you can have multiple clients connected to one server. Like so:
private void listen() throws IOException {
serverSocket = new ServerSocket(port)
while (GlobalFlags.listening) {
new ServerThread(serverSocket.accept();
if (GlobalFlags.exit) {
serverSocket.close();
break;
}
}
}
Where the GlobalFlags are variables to control the listening process and are not really necessary. You could do a while True and just keep listening for ever and ever.
In my project I have a main server controller which had listeners running in Threads. The controller controlled the GlobalFlags. I'm sure instead of using global flags there is a better way to do inter thread communication but for me this was the simplest at the time.
The ServerThread should be looping all the time switching between sending output to the client and receiving input from the client. Like so:
ServerThread(Socket socket) {
super("GameServerThread");
this.socket = socket;
try {
this.socket.setTcpNoDelay(true);
} catch (SocketException e) {
// Error handling
}
this.terminate = false;
}
#Override
public void run() {
try {
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
String inputLine, outputLine;
while ((inputLine = in.readLine()) != null) {
outputLine = processInput(inputLine);
out.println(outputLine);
if (terminate) {
break;
}
}
}
out.close();
in.close();
socket.close();
} catch (Exception e) {
// Error handling, should not use Exception but handle all exceptions by themselves.
}
On the client side you have a thread running through a similar loop, receiving input from the server and then sending output to the server.
In this example processInput is the function used to process the client's input. If you want the server to initiate contact you can make the server send something to the outputstream before listening for input and make the client listen first.
I have extracted this example from one of my own projects and the this.socket.setTcpNoDelay(true) is supposed to make the process faster. Reference here: http://www.rgagnon.com/javadetails/java-0294.html
"java.net.Socket.setTcpNoDelay() is used to enable/disable TCP_NODELAY which disable/enable Nagle's algorithm.
Nagle's algorithm try to conserve bandwidth by minimizing the number of segments that are sent. When applications wish to decrease network latency and increase performance, they can disable Nagle's algorithm (that is enable TCP_NODELAY). Data will be sent earlier, at the cost of an increase in bandwidth consumption. The Nagle's algorithm is described in RFC 896.
You get the current "TCP_NODELAY" setting with java.net.Socket.getTcpNoDelay()"
So to send a message to a specific client you could put all the threads upon creation in an ArrayList so you can keep track of all the currently connected clients. You can have the processInput method halt and polling a queue/variable until another class puts the message to be send in the queue/variable. So how to gain a handle on the class depends on your implementation of processInput. You could give every thread an ID (which is what I did in my project) and maybe have the processInput method poll an ArrayList at index=ID. Then to send output to the client you would have to set the variable at index=ID.
This method seems kind of clunky to me personally but I'm not really sure how else I would do it. You would probably use Queues and have processInput write the input to its Queue and then wait for another class to read it and put its response in the Queue. But I have personally never worked with Queues in java so you should read up on that yourself.
In my knowledge
1) Server hosting TCP socket server -- Possible
2) Multiple clients connected over TCP -- Possible
3) Then I would like to initiate a message from the Server to the client -- Not Possible. The Client has to initiate a connection creation, then the server might be able to send data packets to You. Example: You need to open Facebook website on your browser, Facebook server cannot decide to send its page to your PC on its own because your PC will not have a static IP address, and also if Facebook hypothetically writes code to initiate connection to Your PC, then it is as good as Your PC is the server and Facebook website/server acts as client.
My client application needs to be able to recover in several situations.
When the power is turned on the client reads the address and port from a file and attempts to connect to the server.
If this is the first time this client has been used on this host a default IP address is tried but this may be incorrect.
The user then needs to enter the correct IP address. The port is hard coded.
The way it works now is a one second swing.Timer attempts to get the status of the server...
statusTimer = new Timer(ONE_SECOND, new ActionListener() {
public void actionPerformed(ActionEvent e) {
final byte GET_STATUS = 20;
SendCommand(GET_STATUS, null);
}
});
statusTimer.start();
If there is no connection the user is asked to connect...
private void SendCommand(byte command, byte[] parameters) {
if ((null == socket) || (null == outputStream) || socket.isClosed())
if (JOptionPane.YES_OPTION ==
JOptionPane.showConfirmDialog(null, "Connect?"))
Connect();
...
private void Connect() {
String s = (String)
JOptionPane.showInputDialog(null, "Enter IP Address", ipAddress);
if (validateIp(s)) {
ipAddress = s;
connectTask = new ConnectTask();
connectTask.start();
...
The socket is opened, the io streams are set, and an RxThread is started.
class ConnectTask extends Thread {
#Override public void run() {
try {
if (null == socket) socket = new Socket(ipAddress, TCP_PORT);
if (null == outputStream) outputStream = socket.getOutputStream();
if (null == inputStream) inputStream = socket.getInputStream();
if (null == rxThread) rxThread = new RxThread();
...
There are a few bad things that could happen at this point, for example:
1. The server could be off when the client is turned on. What is the best way for the client to automatically open the socket, set the io streams, and continue when the server is powered on?
2. In the same way, the server might see a power cycle during a read, write, or neither. Is there a good way to automatically recover after power is restored?
3. The IP address may need to be corrected as mentioned above.
It would be nice to handle these and other situations without requiring the user to close and open the client application or power cycle the system.
What kinds of approaches are needed for a bullet-proof java client socket?
This and this are similar but deal with a server sockets
You need to be able to distinguish between first-time usage (when the server details may be wrong, and the user should be prompted) and later usage (when the server may just be down). You could save a file when the user first enters the IP, for example.
After that, you probably want something like: an inner loop where you attempt to connect to the server and read data, with a timeout. If the socket is closed due to a network error then this can be caught with a try-catch block. Put all this into an outer loop so that you try again when disconnected.
Depending on the details, and assuming the amount of data is small, it may well be easiest for your client to open a connection every time rather than attempting to maintain a connection, then sleep in between connections.
If the server is unresponsive, your current code (which creates a new ConnectTask thread each second using a Timer) may end up creating multiple ConnectTasks, one created per second, each trying to connect in parallel, though it's hard to be certain from the partial code you posted.
In Java, how would you set up a socket listener that listened to a socket for a series of bytes that represented a command and on recieving called a method which parsed the incoming data and invoked the appropriate command?
Clarification:
My issue is not with handling the commands (Which might also be error codes or responses to commands from the server) but with creating the socket and listening to it.
More Clarification:
What I want to do is mimic the following line of .Net (C#) code:
_stream.BeginRead(_data,0, _data.Length, new
AsyncCallback(this.StreamEventHandler), _stream);
Where:
_stream is a network stream created from a socket
_data is an array of Byte of length 9
this.StreamHandler is a delegate (function pointer) which get executed when data is read.
I am rewriting a library from C# into Java and the component I am currently writing passes commands to a server over TCPIP but also has to be able to bubble up events/responses to the layer above it.
In C# this seems to be trivial and it's looking less and less so in Java.
Starting from my other answer: The specific part you request is the one that goes into the section: "Magic goes here". It can be done in ohh so many ways, but one is:
final InputStream in = socket.getInputStream();
// This creates a new thread to service the request.
new Thread(new Runnable(){
public void run(){
byte[] retrievedData= new byte[ITEM_LENGTH];
in.read(retrievedData, 0, ITEM_LENGTH);
in.close();
// Here call your delegate or something to process the data
callSomethingWithTheData(retrievedData);
}
}).start();
Have a small main method which sets up the socket and listens for incoming connections. Pass each connection to a worker object (possibly in its own thread).
The worker object should have two APIs: The server and the client. The client API gets a connection and reads data from it, the server API takes a connection and writes data to it.
I like to keep these two in a single class because that makes it much more simple to keep the two in sync. Use a helper class to encode/decode the data for transmission, so you have single point to decide how to transmit integers, commands, options, etc.
If you want to go further, define a command class and write code to serialize that to a socket connection and read it from it. This way, you worker objects just need to declare which command class they handle and the server/client API gets even more simple (at the expense of the command class).
I would
put each command into a class of its own, where each class implements a specific interface (e.g. Command)
create a Map<String,Command> which contains a lookup table from each command string to an instance of the class that implements that command
This should help.
Lesson 1: Socket Communications
The TCP connection provides you with one InputStream and one OutputStream. You could just poll the InputStream continuously for the next command (and its inputs) on a dedicated thread. ByteBuffer.wrap(byte[] array) may be useful in interpreting the bytes as chars, ints, longs, etc. You could also pass objects around using serialization.
Any naive approach most likely will not scale well.
Consider using a REST-approach with a suitable small web-server. Jetty is usually a good choice.
To create an listen to a socket, in a very naive way:
mServerSocket = new ServerSocket(port);
listening = true;
while (listening) {
// This call blocks until a connection is made
Socket socket = serverSocket.accept();
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();
// Here you do your magic, reading and writing what you need from the streams
// You would set listening to true if you have some command to close the server
// remotely
out.close();
in.close();
socket.close();
}
Normally it is a good idea to delegate the processing of the input stream to some other thread, so you can answer the next request. Otherwise, you will answer all requests serially.
You also need to define some kind of protocol of what bytes you expect on the input and output streams, but from your question it looks like you already have one.
You could create an enum with one member per command
interface Comamnd {
// whatever you expect all command to know to perform their function
void perform(Context context);
}
enum Commands implements Command{
ACTIONONE() {
void perform(Context context) {
System.out.println("Action One");
}
},
ACTIONTWO() {
void perform(Context context) {
System.out.println("Action Two");
}
}
}
// initialise
DataInputStream in = new DataInputStream(socket.getInputStream());
// in a loop
byte[] retrievedData= new byte[ITEM_LENGTH];
in.readFully(retrievedData);
String command = new String(retrievedData, 0);
Commands.valueOf(command).perform(context);