Java server connect to other server using sockets - java

I have a project where I have to build a system where multiples server communicate between each other to respond to clients.
I can make the client communicate with the server but I'm having problems on making the servers start a connection between them.
In the code below you can see that I have a list with the ip's of all the server. For each ip the current server tries to connect with the other server. You can also see that the server wait's for connections, in these case, connections from the other servers.
#Override
public void run() {
// Trying to connect with server
for (String serverIp : servers) {
System.out.println("Trying to connect with " + serverIp);
try {
Socket clientSocket = new Socket(serverIp, this.port);
this.clientPool.submit(new ClientThread(clientSocket, this.streamHandler));
} catch (Exception e) {
System.out.println("Error");
}
System.out.println("Connected with " + serverIp);
}
// Receiving connections from other servers
// In these case we call client to the other server
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("Waiting for clients to connect...");
while (true) {
Socket clientSocket = serverSocket.accept();
this.clientPool.submit(new ClientThread(clientSocket, this.streamHandler));
}
// serverSocket.close();
} catch (IOException e) {
Configuration.printError("Error starting server", e);
}
}
The problem is that the server needs to try to connect with the other servers and wait for connections from the other servers. And after receiving a new connection it needs to stop trying to connect to the correspondent server or if the server have success trying to connect with the other server, it needs to stop receiving new connections from that server.
Any suggestions on how to implement this with sockets?

It seems like you try to do this in steps, first all servers try to connect to the others, but no server have started to accept connections yet. And after the clientSocket has connected to servers, you then start to accept connections. It sounds like this can lead to a deadlock.
You know that each server must accept connections from other servers. You also know that each server need to initiate connections to the other servers.
You must either accept connections and initiated connections in two different threads, or you should use an asynchronous/event driven model and manage an event loop.
And after receiving a new connection it needs to stop trying to connect to the correspondent server or if the server have success trying to connect with the other server, it needs to stop receiving new connections from that server.
Here you want to avoid a race. This is easiest to do if each server wait X time before trying to connect to the other servers. This X should be a random delay from startup. E.g. server A waits 5 seconds before connecting, server B waits 1 second, and server C waits 13 seconds before connecting. But server B and C will not initiated any connections since server A already have established connections to those servers.

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.

Java listening on port

We want to capture the data which comes to the system on port say 7777.
public static void main(String[] args) {
try {
final ServerSocket serverSocket = new ServerSocket(7777);
new Thread("Device Listener") {
public void run() {
try {
System.out.println("Listener Running . . .");
Socket socket = null;
while ((socket = serverSocket.accept()) != null) {
System.out.println("| Incoming : "+ socket.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
We have a device which sends data to the port 7777, which comes with a native windows application. The windows native application is receiving data which comes from that device. We have to receive that data on port 7777 through our java project.
In the above code,
The java server socket is created but no incoming connections are received from the device.
The java server socket is receiving connections from telnet command.
The data format which is used by the device and the other native application may be different, but atleast it has to be connected from java server socket. is it correct?
how to receive the data which is transmitted to port 7777.
EDIT:
Ok, the data is received with UDP socket. it is 68 in length. The device documentation doesn't specify any methods to capture this data, because may be it is designed to work with the specified application. We can't contact the manufacturer also. is there any way (if possible) to know the format of incoming bytes. we have tried network sniffers but we cant understand the format.
If you're receiving from the telnet command, then I suspect you have a network-specific issue.
your device isn't talking to the same ip address / hostname that you're configuring telnet with
you have a routing or firewall issue
is your device possibly using UDP rather than TCP ?
The java server socket is created but no incoming connections are received from the device.
So either there is a firewall in the way or the device isn't trying to connect to that port.
The java server socket is receiving connections from telnet command.
So the Java application is listening to that port.
The data format which is used by the device and the other native application may be different, but at least it has to be connected from java server socket. is it correct?
Yes.
how to receive the data which is transmitted to port 7777.
First you have to accept the connection. On the evidence here the device isn't connecting to port 7777 at all. I suggest some network sniffing is in order to see what it really is doing.

Java Threadpool TCP Server (Port keeps changing!!)

Good Day,
I was taking a look at this tutorial to do a TCP Threadpool server.
http://tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.html
It works great for listening/RECEIVING to clients and processing, and returning a response. There is a class inside that I pass in WorkerRunnable into, and that basically prints out the remote socket address (who it was sent from)
public void run(){
synchronized(this){
this.runningThread = Thread.currentThread();
}
openServerSocket();
while(! isStopped()){
Socket clientSocket = null;
try {
clientSocket = this.serverSocket.accept();
} catch (IOException e) {
if(isStopped()) {
System.out.println("Server Stopped.") ;
return;
}
throw new RuntimeException(
"Error accepting client connection", e);
}
this.threadPool.execute(
new WorkerRunnable(clientSocket,
"Thread Pooled Server"));
}
this.threadPool.shutdown();
System.out.println("Server Stopped.") ;
}
The problem is. The remote address is supposed to stay fixed (I am working within my own home wifi router). However, the IP address of the sender stays the same, but the port keeps changing!!
This is a big problem for me..as I need to be able to return a response to the user for future tasks and I actually save this address to use again to send data. When I ran this in a single TCP thread..it stayed fixed (the port).
Why does the threadpool cause the TCP remote address port to keep changing?
With TCP, the client socket port is most of the time (almost 99%, except for specific protocols) randomly chosen. But to you don't have to know it, the only thing you have to do is to keep the clientSocket reference to write back data to the client. If you want to send data to the other host after that the connection is closed, you have to start a ServerSocket on both sides with a fixed port.
Even if you test from same machine the client port will be random by default. I am not sure if there is any way to set the client source port. However, if you use netstat or capture the packet you can be sure the source port is different for every connection.

Why do sockets not die when server dies? Why does a socket die when server is alive?

I try to play with sockets a bit. For that I wrote very simple "client" and "server" applications.
Client:
import java.net.*;
public class client {
public static void main(String[] args) throws Exception {
InetAddress localhost = InetAddress.getLocalHost();
System.out.println("before");
Socket clientSideSocket = null;
try {
clientSideSocket = new Socket(localhost,12345,localhost,54321);
} catch (ConnectException e) {
System.out.println("Connection Refused");
}
System.out.println("after");
if (clientSideSocket != null) {
clientSideSocket.close();
}
}
}
Server:
import java.net.*;
public class server {
public static void main(String[] args) throws Exception {
ServerSocket listener = new ServerSocket(12345);
while (true) {
Socket serverSideSocket = listener.accept();
System.out.println("A client-request is accepted.");
}
}
}
And I found a behavior that I cannot explain:
I start a server, than I start a client. Connection is successfully established (client stops running and server is running). Then I close the server and start it again in a second. After that I start a client and it writes "Connection Refused". It seems to me that the server "remember" the old connection and does not want to open the second connection twice. But I do not understand how it is possible. Because I killed the previous server and started a new one!
I do not start the server immediately after the previous one was killed (I wait like 20 seconds). In this case the server "forget" the socket from the previous server and accepts the request from the client.
I start the server and then I start the client. Connection is established (server writes: "A client-request is accepted"). Then I wait a minute and start the client again. And server (which was running the whole time) accept the request again! Why? The server should not accept the request from the same client-IP and client-port but it does!
When you close the server , the OS will keep the socket alive for a while so it can tell the client the connection has been closed. This involves timeouts and retransmissions which can take some time. You might find some info here and here. If you want your server to be able to immediately rebind the same socket, call setReuseAddress(true) on it, though it might be the client sockets that's in a TIME_WAIT state.
The socket is no longer in TIME_WAIT state, and can be reused again by any program.
Your client code just connects, closes the socket and then exits. As far as the server/OS tcp stack is concerned, these are different connections - it's fine to reuse the source port as long as any prior connection have been torn down. (Note that the OS might not tear down all of the housekeeping of the connection immediately after you call .close() or your program exits, there's some time delay involved so it can be sure all packets have been sent/received)
It is likely the operating system has not yet shutdown the sockets, try the netstat command (should work on Windows or Unix/Linux). If you run it immediately after you close client or server you should still the socket in "TIME_WAIT" "CLOSE_WAIT" or something similar. You wont be able to reuse those ports until they are fully closed.
Per Question #3: Many clients can connect to a server attached to a single port. Apache runs on port 80 but that doesn't mean only one person can view your website at a time. Also you are closing your client socket before you're opening a new one.

Categories

Resources