Java client/server application with sockets? - java

I'm writing a java package that will be called by another language (matlab). If my matlab process ends, I want the Java process to keep running. Whenever matlab starts again, it should be able to communicate with the existing running process. So I think I need to have the Java application communicating through sockets in a client/server model. I envision having a simple set of functions:
startServer(host, port)
runCommand(server, command...)
stopServer(host, port)
I have never done anything like this before. Am I thinking about it in the right way, or is there an easier way of building an application that can run independently of it's parent's process? What's the best modern way of doing this (e.g. are there any good Apache packages)? Can anyone provide a simple demo or point me to a tutorial on communicating with a process through sockets?
[Edit] For some clarification, matlab is able to instantiate a java object and run java code within itself. So the startServer() function in matlab would run java code that will check if a java process is already running on that port and if not, start the server process.
I'm not tied to using sockets by any means (in case it isn't obvious, I'm mostly a matlab developer), so if there's something easier, I'm all for it. I just need to be able to run things independently of matlab, but have matlab control those processes (through java).

The server listens for a connection. When a connection is established by a client. The client can send data. In the current example the client sends the message "Hi my server". To terminate the connection, the client sends the message "bye". Then the server sends the message "bye" too. Finally the connection is ended and the server waits for an other connection. The two programs should be running in the same machine. however if you want to run them in two different machines, you may simply change the address "localhost" by the IP address of the machine where you will run the server.
The server
import java.io.*;
import java.net.*;
public class Provider{
ServerSocket providerSocket;
Socket connection = null;
ObjectOutputStream out;
ObjectInputStream in;
String message;
Provider(){}
void run()
{
try{
//1. creating a server socket
providerSocket = new ServerSocket(2004, 10);
//2. Wait for connection
System.out.println("Waiting for connection");
connection = providerSocket.accept();
System.out.println("Connection received from " + connection.getInetAddress().getHostName());
//3. get Input and Output streams
out = new ObjectOutputStream(connection.getOutputStream());
out.flush();
in = new ObjectInputStream(connection.getInputStream());
sendMessage("Connection successful");
//4. The two parts communicate via the input and output streams
do{
try{
message = (String)in.readObject();
System.out.println("client>" + message);
if (message.equals("bye"))
sendMessage("bye");
}
catch(ClassNotFoundException classnot){
System.err.println("Data received in unknown format");
}
}while(!message.equals("bye"));
}
catch(IOException ioException){
ioException.printStackTrace();
}
finally{
//4: Closing connection
try{
in.close();
out.close();
providerSocket.close();
}
catch(IOException ioException){
ioException.printStackTrace();
}
}
}
void sendMessage(String msg)
{
try{
out.writeObject(msg);
out.flush();
System.out.println("server>" + msg);
}
catch(IOException ioException){
ioException.printStackTrace();
}
}
public static void main(String args[])
{
Provider server = new Provider();
while(true){
server.run();
}
}
}
The client
import java.io.*;
import java.net.*;
public class Requester{
Socket requestSocket;
ObjectOutputStream out;
ObjectInputStream in;
String message;
Requester(){}
void run()
{
try{
//1. creating a socket to connect to the server
requestSocket = new Socket("localhost", 2004);
System.out.println("Connected to localhost in port 2004");
//2. get Input and Output streams
out = new ObjectOutputStream(requestSocket.getOutputStream());
out.flush();
in = new ObjectInputStream(requestSocket.getInputStream());
//3: Communicating with the server
do{
try{
message = (String)in.readObject();
System.out.println("server>" + message);
sendMessage("Hi my server");
message = "bye";
sendMessage(message);
}
catch(ClassNotFoundException classNot){
System.err.println("data received in unknown format");
}
}while(!message.equals("bye"));
}
catch(UnknownHostException unknownHost){
System.err.println("You are trying to connect to an unknown host!");
}
catch(IOException ioException){
ioException.printStackTrace();
}
finally{
//4: Closing connection
try{
in.close();
out.close();
requestSocket.close();
}
catch(IOException ioException){
ioException.printStackTrace();
}
}
}
void sendMessage(String msg)
{
try{
out.writeObject(msg);
out.flush();
System.out.println("client>" + msg);
}
catch(IOException ioException){
ioException.printStackTrace();
}
}
public static void main(String args[])
{
Requester client = new Requester();
client.run();
}
}

If you decide to go with a custom socket-level protocol, then I can suggest that you use JBoss Netty at the java end:
In other words, Netty is a NIO client
server framework which enables quick
and easy development of network
applications such as protocol servers
and clients. It greatly simplifies and
streamlines network programming such
as TCP and UDP socket server.

It sounds like you need the Java server process to be independent of the Matlab process. So when the Matlab process starts/stops, the Java server continues. The Java server will sit and wait for incoming connections, and handle multiple connections, disconnects etc.
Here's a tutorial for writing a Java socket server (note it's part of a larger tutorial on Java client/server socket communication).
One challenge you will face (and I can't help you here being Matlab-unaware) is creating or using a platform-independent means of creating the actual message, whether that's using a binary representation, XML (looks like Matlab has some XML functionality) or other.

If, as you say, matlab can run java code from within itself, then there should be no reason that you can't use RMI to communicate between matlab and java server. RMI is vastly easier than raw socket programming.

The easy part is the tutorial: Sun's Sockets Tutorial taught me everything I needed to know about sockets programming, and will hopefully do for you too.
I think you need to clarify your thinking about the commands you want to support, in particular the first and 3rd:
If the Java process isn't running, who's going to respond to your startServer command? And if it is running, who needs it? :)
You can certainly implement a stopServer command. But that would be kind of like having your computer pulling its own power cord out of the wall. We return to the previous question: If the server's stopped, who'll hear the start command?
As I understand it, the only remote operation you need is the middle one.
However... socket programming is only moderately fun. You may consider looking at the RMI tutorial for an alternative.

Any reason that you can't just implement your java server as a collection of servlets in tomcat? Tomcat comes with all the tools to autostart and keep the server running, you can implement SOAP service or RESTful web services pretty easily which will help to decouple your matlab code from your java code.

Related

How do I make a client-server Java application to send messages on one port but receive them on another?

I am currently trying to make an application that will send messages to a server using one port, but will receive messages on another port. However, based on tutorials I have followed, it looks like the act of connecting to the server is where ports come into play and my client is receiving and sending messages on the same port. How do I make it so it sends on one port but receives on the other?
Here is the code that I think is relevant from the client side (I put some stuff that seems unrelated because I think they are things that would be altered by receiving on one port but sending on another, and ignore the comment about replacing inetaddress, that is just me working on implementing this in a gui):
public void startRunning(){
try{
connectToServer();
setupStreams();
whileChatting();
}catch(EOFException eofException){
showMessage("\n Client terminated connection");
}catch(IOException ioException){
ioException.printStackTrace();
}finally{
closeStuff();
}
}
//connect to server
private void connectToServer() throws IOException{
showMessage("Attempting connection... \n");
connection = new Socket(InetAddress.getByName(serverIP), 480);//replace serverIP with ipTextField.getText or set serverIP to equal ipTextField.getText? Same with port number.
showMessage("Connected to: " + connection.getInetAddress().getHostName() );
}
//set up streams to send and receive messages
private void setupStreams() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("\n Streams are good! \n");
}
//while talking with server
private void whileChatting() throws IOException{
ableToType(true);
do{
try{
message = (String) input.readObject();
showMessage("\n" + message);
}catch(ClassNotFoundException classNotfoundException){
showMessage("\n Don't know that object type");
}
}while(!message.equals("SERVER - END"));
}
//send messages to server
private void sendMessage(String message){
try{
output.writeObject("CLIENT - " + message);
output.flush();
showMessage("\nCLIENT - " + message);
}catch(IOException ioException){
messageWindow.append("\n something messed up ");
}
}
//change/update message window
private void showMessage(final String m){
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
messageWindow.append(m);
}
}
);
}
EDIT/UPDATE: To help clarify some things, here is some more information. The device that sends the first message is connected to a sensor, and it sends information when that sensor detects something to the other device. The receiving device sends a message back on a different port telling the original sending device how to respond. Lets name these two devices the "reporter-action taker" and the "decision maker-commander".
If you want to use TCP/IP sockets you can't use a a socket to send and another to read. That's not what they are for.
If you use a centralized distributed algorithm (server/client communication) you have to set the server to listen on a single socket port with the ServerSocket class: then the server tries to accept clients through that socket.
Example:
ServerSocket listener = new ServerSocket(Port)
While (true) {
new Clienthandler(listener.accept());
}
The server will listen on that port, and when a client tries to connect to that port if it is accepted the server launches its handler. On this handler constructor the Socket object used on the client is received on an argument and can then be used to get the writers and the readers. The reader on this handler class will be the writer on the client class and vice-versa, maybe that's what you were looking for.
Your question about using two ports in this manner is a bit strange. You state that you have a client and a server and that they should communicate on different ports.
Just to clarify picture the server as a hanging rack for jackets with several hooks in a row. Each port the server listened on represents a hook. When it comes to the client server relationship the client or jacket knows where to find its hook, however the hook is blind and have no idea where to find jackets.
Now, the client selects a port or a hook and connects to it. The connection is like a pipeline with two pipes. One for the client to deliver data to the server with and the other to send data from the server back to the client. When the connection is established data can be transferred both ways. This means that we only need one port open on the server to send data both from the client to the server and in the opposite direction.
The reason for only having one open port open on the server for the clients to connect to is that holding an open port for connections is hard to do on a regular client computer. The normal desktop user will be behind several firewalls blocking incoming connections. If that wasn't the case the client would probably be hacked senseless from malicious viruses.
Moving on with the two port solution we could not call this a client server connection per say. It would be more like a peer to peer connection or something like that. But if this is what you want to do, the application connecting first would have to start by telling the other application what ip and port to use for connecting back, it should probably also want to give some kind of token that are to be used to pair the new incoming connection when connecting back.
You should take note that making such an implementation is not a good idea most of the time as it complicates things a whole lot for simple data transfer between a client and server application.

how to run a server socket on amazon EC2

I'm trying to write an android app that interacts with a server. I'm trying now to write the server side with sockets. I created an instance of ec2 and ran it. I connected to it with putty and ran a simple "hello world" java program. Now I'm trying to run a server which use a socket, but I get this as the server socket: ServerSocket[addr=0.0.0.0/0.0.0.0,localport=5667].
This is my code, very basic so far:
public class EchoServer {
public static void main(String[] args) throws IOException {
int portNumber = 5667;
System.out.println("server socket main");
try (ServerSocket serverSocket = new ServerSocket(portNumber);
) {
System.out.println(serverSocket.toString());
} catch (IOException e) {
System.out
.println("Exception caught when trying to listen on port "
+ portNumber + " or listening for a connection");
System.out.println(e.getMessage());
}
}
}
What should I do to run the server so I could connect to it via my andriod device?
Thanks!
You are on the right track. 0.0.0.0 simply means:
A way to specify "any IPv4-interface at all". It is used in this way when configuring servers (i.e. when binding listening sockets).
Next, your server will need to listen for incoming connections by using SocketServer.accept().
And then of course you'll want to receive and send data on the socket. This tutorial should help.
Finally, if you plan on serving multiple clients simultaneously with your server, you will want to consider concurrency and scalability, and perhaps consider using a framework like Netty.

Possible Socket + ServerSocket in java?

We are making an somewhat RTS networked game in java. i have this main server that accepts other players which has the serversocket. Then on our game when you created your own game room
i filtered all the players that has joined my room.then when the game starts the creator of the room should be the host. should i be still using my main server or should i establish a new serversocket for those who are connected to my room? and 1 more thing should a inputstream.readObject() what for an message to go for another loop?or it continuously looping? here is the sample code snippet for the inputstream.
public void run() {
while (running) {
try {
inStream = new ObjectInputStream(client.getInputStream());
command = (String) inStream.readObject();
Thread.sleep(10);
}//try
catch (Exception e) {
e.printStackTrace();
}//catch
}//while
}//run
////accepting new client
while (running) {
try {
clientConnecting = serverSocket.accept();
new TCPServerHandle(clientConnecting).start();
Thread.sleep(10);
}//try
catch (Exception e) {
e.printStackTrace();
}//catch
}//while
You could deffinitely create a second ServerSocket for the "party" to communicate with the host. Incoming packets are demultiplexed to the correct process, using port numbers. You can set multiple TCPServerSockets to listen and accept incoming connection requests on different ports.
ServerSocket welcomeSocket = new ServerSocket(portNumber);
Socket clientSocket = welcomeSocket.accept();
And yes, it is in many cases more efficient to use a combination of TCP and UDP, because as you mention some data is more critical than other. UDP only provides a best effort service, where packets can get lost. If you want to setup a UDP socket:
DatagramSocket UDPSocket = new DatagramSocket();
Using blocking I/O with Object I/O streams aren't optimal conditions for an RTS because you don't want other clients to wait during the login process of another client. You might be thinking that you could just multi-thread everything to avoid the wait but it wouldn't make much of a difference because there are still blocking read/write operations. Also, with Object I/O streams, all objects sent have to be serialized first (known as serialization), which could be a pretty lengthy process depending on your user-base. If there are a lot of players, literally every millisecond counts. You should use non-blocking I/O (such as NIO) along with ByteBuffers. I would suggest looking at an NIO tutorial instead, this is a very detailed tutorial on how to make a simple server-client application.

Android Socket Client Runnable didn't stop

I am using the following code to connect my client to the server. The problem is this doesn't terminate and I am unable to start a new activity after this one.
I think the problem is either I don't close the socket or the thread doesn't terminate.
I start the thread in onCreate()
cThread = new Thread(new ClientThread());
cThread.start();
And here is my Runnable
public class ClientThread implements Runnable {
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
Log.d("ClientActivity", "C: Connecting...");
socket = new Socket(serverAddr, 8080);
connected = true;
while (connected) {
try {
Log.d("ClientActivity", "C: Sending command.");
PrintWriter out = new PrintWriter(new BufferedWriter(new
OutputStreamWriter(socket
.getOutputStream())), true);
// where you issue the commands
out.println(serverIpAddress);
Log.d("ClientActivity", "C: Sent.");
} catch (Exception e) {
Log.e("ClientActivity", "S: Error while sending", e);
}
connected = false;
}
//socket.close();
Log.d("ClientActivity", "C: Closed.");
} catch (Exception e) {
Log.e("ClientActivity", "C: Error while connecting", e);
connected = false;
}
}
}
Your program is quite useless. Assuming the socket is estabilished, the while loop is executed only once because, at the end of the first iteration, you set connected to false, thus disabling any further cycle. You don't flush your buffered output to ensure it's written, and you don't even read from the socket, so I wonder what your custom protocol looks like... At this moment, all your program does is simply writing a string to a server, then exiting. We can't even tell why you are not able to start a new activity, because in the supplied code there is nothing preventing you from doing so.
There are basically two kinds of TCP protocols
Request-response based (like HTTP, not suitable for a chat program). The client estabilishes a connection, makes a request, reads the response, makes another request, reads the new response and so on, till the client has finished its job. A graphical client will need 2 threads at least: one for the UI update and the other for network communication.
Client and server both send messages at random times. This leverages the full-duplex capability of socket communication, however you'll need at least three threads in a GUI program: one for the UI, one blocked on the socket's input stream, and one for writing. Things get quite messy because you'll likely share streams and have to synchronize by hand.
If this is yet another chat program, I'd suggest not to design your own TCP protocol, and start with a standard technology like WebSockets. There are Java clients available, and you may test your server simply with a bit of Javascript in your browser, and there are even more choices on the server side (Socket.IO - for a JS solution, Jetty, Glassfish, ...).
After you get some experience and become acquainted with the job, you may try to design your own custom TCP protocol. By the time, you'll have learned at least the basics of sockets, threads and Android programming.
BTW, you may want to take a look at the Service API for background tasks which don't require user interaction.

Reliable TCP/IP in Java

Is there a way to have reliable communications (the sender get informed that the message it sent is already received by the receiver) using Java TCP/IP library in java.net.*? I understand that one of the advantages of TCP over UDP is its reliability. Yet, I couldn't get that assurance in the experiment below:
I created two classes:
1) echo server => always sending back the data it received.
2) client => periodically send "Hello world" message to the echo server.
They were run on different computers (and worked perfectly). During the middle of the execution, I disconnected the network (unplugged the LAN cable). After disconnected, the server still keep waiting for a data until a few seconds passed (it eventually raised an exception). Similarly, the client also keep sending a data until a few seconds passed (an exception is raised).
The problem is, objectOutputStream.writeObject(message) doesn't guarantee the delivery status of the message (I expect it to block the thread, keep resending the data until delivered). Or at least I get informed, which messages are missing.
Server Code:
import java.net.*;
import java.io.*;
import java.io.Serializable;
public class SimpleServer {
public static void main(String args[]) {
try {
ServerSocket serverSocket = new ServerSocket(2002);
Socket socket = new Socket();
socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
ObjectInputStream objectInputStream = new ObjectInputStream(
inputStream);
while (true) {
try {
String message = (String) objectInputStream.readObject();
System.out.println(message);
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Client code:
import java.net.*;
import java.io.*;
public class SimpleClient {
public static void main(String args[]) {
try {
String serverIpAddress = "localhost"; //change this
Socket socket = new Socket(serverIpAddress, 2002);
OutputStream outputStream = socket.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(
outputStream);
while (true) {
String message = "Hello world!";
objectOutputStream.writeObject(message);
System.out.println(message);
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
If you need to know which messages have arrived in the peer application, the peer application has to send acknowledgements.
If you want this level of guarantees it sounds like you really want JMS. This can ensure not only that messages have been delivered but also have been processed correctly. i.e. there is no point having very reliable delivery if it can be discarded due to a bug.
You can monitor which messages are waiting and which consumers are falling behind. Watch a producer to see what messages it is sending, and have messages saved when it is down and are available when it restarts. i.e. reliable delivery even if the consumer is restarted.
TCP is always reliable. You don't need confirmations. However, to check that a client is up, you might also want to use a UDP stream with confirmations. Like a PING? PONG! system. Might also be TCP settings you can adjust.
Your base assumption (and understanding of TCP) here is wrong. If you unplug and then re-plug, the message most likely will not be lost.
It boils down on how long to you want the sender to wait. One hour, one day? If you'd make the timeout one day, you would unplug for two days and still say "does not work".
So the guaranteed delivery is that "either data is delivered - or you get informed". In the second case you need to solve it on application level.
You could consider using the SO_KEEPALIVE socket option which will cause the connection to be closed if no data is transmitted over the socket for 2 hours. However, obviously in many cases this doesn't offer the level of control typically needed by applications.
A second problem is that some TCP/IP stack implementations are poor and can leave your server with dangling open connections in the event of a network outage.
Therefore, I'd advise adding application level heartbeating between your client and server to ensure that both parties are still alive. This also offers the advantage of severing the connection if, for example a 3rd party client remains alive but becomes unresponsive and hence stops sending heartbeats.

Categories

Resources