Communicating through two separate computer using java sockets - java

I am trying to make a chat server and client that can communicate over two separate computers connected to the internet. One of them is connected to wifi and another one is through a modem. Here is my server code.
GreetingServer.java
import java.net.*;
import java.io.*;
public class GreetingServer extends Thread
{
private ServerSocket serverSocket;
public GreetingServer(int port) throws IOException
{
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(100000);
}
public void run()
{
while(true)
{
try
{
System.out.println("Waiting for client on port " +
serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to "
+ server.getRemoteSocketAddress());
DataInputStream in =
new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out =
new DataOutputStream(server.getOutputStream());
out.writeUTF("Thank you for connecting to "
+ server.getLocalSocketAddress() + "\nGoodbye!");
server.close();
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
public static void main(String [] args)
{
int port = Integer.parseInt("6066");
try
{
Thread t = new GreetingServer(port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
GreetingClient.java
import java.net.*;
import java.io.*;
public class GreetingClient2
{
public static void main(String [] args)
{
String serverName = "10.2.3.100";
int port = Integer.parseInt("6066");
try
{
System.out.println("Connecting to " + serverName +
" on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to "
+ client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("Hello from "
+ client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
client.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
The IP address in Client code is of the computer where the server is running acquired by InetAddress.getLocalHost().getHostAddress(). When I run the server, it waits for the client. And when I run the client code from another computer, it doesn't connect. Is it possible to communicate like this through sockets in java ?

Yes, it is possible.
Your server has to have an external ip.
Also if your server is connected via WiFi, check router firewall settings.

Related

How to get Java sockets work with public IP on google cloud

I'm planning to create a server and run it on google cloud VM, this code is working fine in the localhost but it won't run on External IP.
import java.net.*;
import java.io.*;
public class Server extends Thread {
private ServerSocket serverSocket;
public Server(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
public void run() {
while(true) {
try {
System.out.println("Waiting for Connection ");
Socket server = serverSocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("Goodbye");
server.close();
} catch (SocketTimeoutException s) {
System.out.println("Socket timed out!");
break;
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
public static void main(String [] args) throws UnknownHostException {
int port = 4999;
try {
Thread t = new Server(port);
t.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
and this is for the client
import java.net.*;
import java.io.*;
public class Client {
public static void main(String [] args) {
String serverName = "localhost";
int port = Integer.parseInt("4999");
try {
System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("[Client]Hello from " + client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
System.out.println("[Server] " + in.readUTF());
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
and this is the net config of the google VM instance:
Internal ip-> 10.138.0.13 (nic0) | External ip-> 34.83.94.126
can you please tell me how to get it running on a public ip.

How can I communicate between a server and a client using AWS when they are on different networks?

I am trying to establish a basic connection with my server from the client program. When I run my client/server on the same network, it works fine, but I don't know where to start when my client program is on my PC but my server program is on the EC2 instance.
I have set up an EC2 linux instance on AWS, and have loaded the server code onto it. The Client is on my PC.
To run the server, I'm using:
java GreetingServer 6000
To run the client, I'm using:
java GreetingClient <EC2 Public IP> 6000
I'm new to AWS and server-client communication, so if you know any good tutorials for this, that would be great!
Server Code:
// File Name GreetingServer.java
import java.net.*;
import java.io.*;
public class GreetingServer extends Thread {
private ServerSocket serverSocket;
public GreetingServer(int port) throws IOException {
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
}
public void run() {
while(true) {
try {
System.out.println("Waiting for client on port " +
serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("Thank you for connecting to " + server.getLocalSocketAddress()
+ "\nGoodbye!");
server.close();
} catch (SocketTimeoutException s) {
System.out.println("Socket timed out!");
break;
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
public static void main(String [] args) {
int port = Integer.parseInt(args[0]);
try {
Thread t = new GreetingServer(port);
t.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client Code:
// File Name GreetingClient.java
import java.net.*;
import java.io.*;
public class GreetingClient {
public static void main(String [] args) {
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try {
System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to " + client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("Hello from " + client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

java.net.BindException: Address already in use: Cannot bind

I am sorry, I have searched but seem that all the answers dont fix my problem. I got this error when trying to create a ServerSocket to reply to multiple client message.
My server code:
package Server;
import java.net.*;
import java.io.*;
public class Server {
public final static int defaultPort = 7;
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(defaultPort);
int i = 0;
while (true) {
try {
System.out.println("Server is running on port "
+ defaultPort);
Socket s = ss.accept();
System.out.println("Client " + i + " connected");
RequestProcessing rp = new RequestProcessing(s, i);
i++;
rp.start();
} catch (IOException e) {
System.out.println("Connection Error: " + e);
}
}
} catch (IOException e) {
System.err.println("Create Socket Error: " + e);
} finally {
}
}
}
class RequestProcessing extends Thread {
Socket channel;
int soHieuClient;
public RequestProcessing(Socket s, int i) {
channel = s;
clientNo = i;
}
public void run() {
try {
byte[] buffer = new byte[6000];
DatagramSocket ds = new DatagramSocket(7);
while (true) {
DatagramPacket incoming = new DatagramPacket(buffer,
buffer.length);
ds.receive(incoming);
String theString = new String(incoming.getData(), 0,
incoming.getLength());
System.out.println("Client " + clientNo
+ " sent: " + theString);
if ("quit".equals(theString)) {
System.out.println("Client " + clientNo
+ " disconnected");
ds.close();
break;
}
theString = theString.toUpperCase();
DatagramPacket outsending = new DatagramPacket(
theString.getBytes(), incoming.getLength(),
incoming.getAddress(), incoming.getPort());
System.out.println("Server reply to Client "
+ clientNo + ": " + theString);
ds.send(outsending);
}
} catch (IOException e) {
System.err.println(e);
}
}
}
and my Client code:
package Client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
public class Client extends Object {
public final static int serverPort = 7;
public static void main(String[] args) {
try {
DatagramSocket ds = new DatagramSocket();
InetAddress server = InetAddress.getByName("192.168.109.128");
Socket s = new Socket("192.168.109.128", 7);
String theString = "";
do {
System.out.print("Enter message: ");
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
theString = br.readLine();
byte[] data = theString.getBytes();
DatagramPacket dp = new DatagramPacket(data, data.length,
server, serverPort);
ds.send(dp);
System.out.println("Sent to server server: " + theString);
byte[] buffer = new byte[6000];
DatagramPacket incoming = new DatagramPacket(buffer,
buffer.length);
ds.receive(incoming);
System.out.print("Server reply: ");
System.out.println(new String(incoming.getData(), 0, incoming
.getLength()));
} while (!"quit".equals(theString));
s.close();
} catch (IOException e) {
System.err.println(e);
}
}
}
With the first Client connect, it works smoothly. But from the second Client, it throws java.net.BindException: Address already in use: Cannot bind.
Second Client can also send and receive message, but the Client No is still 0.
Server is running on port 7
Client 0 connected
Server is running on port 7
Client 0 sent: msg 0
Server reply to Client 0: MSG 0
Client 1 connected
Server is running on port 7
java.net.BindException: Address already in use: Cannot bind
Client 0 sent: msg 1 <<-- this one is sent from client 1 but Client No is 0
Server reply to Client 0: MSG 1
So, in RequestProcessing.run you decide to ignore the socket received at constructor and open a DatagramSocket on the same port as the one you are listening. What did you expect it will happen?
class RequestProcessing extends Thread {
Socket channel;
int soHieuClient;
public RequestProcessing(Socket s, int i) {
// *****************
// The processor should be using this socket to communicate
// with a connected client *using TCP Streams*
channel = s;
clientNo = i;
}
public void run() {
try {
byte[] buffer = new byte[6000];
// *****************************
// But, instead of using the this.channel, your code
// decides to ignore the TCP socket,
// then open another UDP *"server-side like"* socket.
// First time it's OK, but the second thread attempting
// to open another DatagramSocket on the same port will fail.
// It's like attempting to open two TCP ServerSockets on the
// same port
DatagramSocket ds = new DatagramSocket(7);
[Extra]
You will need to decide what protocol you'll be using: if you use a ServerSocket/Socket pair, then probably you want TCP communications, so no DatagramSockets.
If you want UDP communication, the ServerSocket/Socket has little to do with your approach and you'll need to use DatagramSocket. Construct it:
with a port on the serverside - and do it only once.
without any port for the client side then qualify each and every DatagramPackets with the server address and port.
See a tutorial on Oracle site on Datagram client/server configurations.
Everytime you receive a new client TCP connection on your main server socket, you spin up another instance of a RequestProcessing class. The first time you start the RequestProcessing instance thread, it successfully binds to UDP port 7. But then the second client connects and you try to spin up another instance of RequestProcessing while another one already exists. That's not going to work.
You should probably amend you protocol such that the RequestProcessing class picks a new port each time and signals back through to the TCP socket which port was chosen.
But if it was me, I would do this. Have a single RequestProcessing instance for all clients. Given that your UDP echo socket is just sending back a response to the address from which the packet arrived from, you only need one instance of this class.
A TCP solution:
An utility class (I'm too lazy to write the same code in multiple places):
public class SocketRW {
Socket socket;
BufferedReader in;
PrintWriter out;
public SocketRW(Socket socket)
throws IOException
{
super();
this.socket = socket;
if(null!=socket) {
this.in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.out=new PrintWriter(socket.getOutputStream());
}
}
public String readLine()
throws IOException {
return this.in.readLine();
}
public void println(String str) {
this.out.println(str);
}
public Socket getSocket() {
return socket;
}
public BufferedReader getIn() {
return in;
}
public PrintWriter getOut() {
return out;
}
}
Server code - no more datagrams, just using Input/Output streams from the sockets, wrapped as Reader/Writer using the utility
public class TCPServer
implements Runnable // in case you want to run the server on a separate thread
{
ServerSocket listenOnThis;
public TCPServer(int port)
throws IOException {
this.listenOnThis=new ServerSocket(port);
}
#Override
public void run() {
int client=0;
while(true) {
try {
Socket clientConn=this.listenOnThis.accept();
RequestProcessing processor=new RequestProcessing(clientConn, client++);
processor.start();
} catch (IOException e) {
break;
}
}
}
static public void main(String args[]) {
// port to be provided as the first CLI option
TCPServer server=new TCPServer(Integer.valueOf(args[0]));
server.run(); // or spawn it on another thread
}
}
class RequestProcessing extends Thread {
Socket channel;
int clientNo;
public RequestProcessing(Socket s, int i) {
channel = s;
clientNo = i;
}
public void run() {
try {
SocketRW utility=new SocketRW(this.channel);
while (true) {
String theString=utility.readLine().trim();
System.out.println("Client " + clientNo
+ " sent: " + theString);
if ("quit".equals(theString)) {
System.out.println("Client " + clientNo
+ " disconnected");
this.channel.close();
break;
}
theString = theString.toUpperCase();
utility.println(theString);
}
} catch (IOException e) {
System.err.println(e);
}
}
}
Client code - no more datagram sockets, using the same IO streams of the socket.
class TCPClient
implements Runnable // just in case you want to run multithreaded clients
{
Socket socket;
public TCPClient(InetAddress serverAddr, int port)
throws IOException {
this.socket=new Socket(serverAddr, port);
}
public void run() {
String theString="";
InputStreamReader isr = new InputStreamReader(System.in);
try {
SocketRW utility=new SocketRW(this.socket);
BufferedReader br = new BufferedReader(isr);
do {
System.out.print("Enter message: ");
theString = br.readLine().trim();
utility.println(theString);
System.out.println("Sent to server server: " + theString);
String received=utility.readLine();
System.out.println("Server reply: "+received);
} while (!"quit".equals(theString));
}
catch(IOException e) {
e.printStackTrace();
}
}
static public void main(String[] args) {
int port=Integer.valueOf(args[0]); // will throw if its no OK.
TCPClient client=new TCPClient(
InetAddress.getByName("192.168.109.128"),
port
);
client.run();
}
}

Java - Which IP to use for the ServerSocket and Socket classes?

I just recently found the ServerSocket and Socket class found in the Java library and so I wanted to make a simple messaging app. The purpose of the app is to be able to communicate with someone on a different network than mine (I am the server side and have my own client side).
Here is the Messenger_Server.java's connecting method
public static void main (String [] args)throws IOException{
InetAddress ip;
try{
final int PORT = 444;
ip = InetAddress.getLocalHost();
ServerSocket server = new ServerSocket(PORT);
System.out.println("Waiting for clients...");
System.out.println(server.getInetAddress() + " " + ip.getHostAddress());
while(true){
Socket sock = server.accept();
connectionArray.add(sock);
System.out.println("Client connected from " + sock.getLocalAddress().getHostName());
addUserName(sock);
Messenger_Server_Return chat = new Messenger_Server_Return(sock);
Thread X = new Thread(chat);
X.start();
}
} catch(Exception e) {
e.printStackTrace();
}
}
Here is the client's connecting method from Messenger_Client.java
public static void connect(){
try{
final int PORT = 444;
// the ip below is the one i get as my ipv4
Socket sock = new Socket ("10.122.***.***",PORT);
System.out.println("you be connected to: " + InetAddress.getByAddress(InetAddress.getLocalHost().getAddress()));
chatClient = new Messenger_Client(sock);
PrintWriter out = new PrintWriter(sock.getOutputStream());
out.println(userName);
out.flush();
Thread X = new Thread(chatClient);
X.start();
}catch (Exception X){
X.printStackTrace();
JOptionPane.showMessageDialog(null, "Server not responding.");
System.exit(0);
}
}
So I gave the client side of the program to my friend and he said the host could not be found. Which IP should I use so my friend can connect to my ServerSocket, and could there be anything limiting my friend from connecting to me?

Why I can't connect two different laptops via WiFi?

This is a simple client-server program. It works fine when executed in a single computer. But, it doesn't work when executed in two different laptops connected using WiFi.
Here's the code:
Server:
public class Server
{
private static int port;
private ServerSocket serverSocket;
public void GreetingServer(int port) throws IOException
{
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(20000);
while(true)
{
try
{
System.out.println("Waiting for client");
Socket server = serverSocket.accept();
System.out.println("Connected");
DataInputStream in =new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("Thank you for connecting to ");
server.close();
}
catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}
catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
public static void main(String [] args)
{
port=9001;
try
{
Server s=new Server();
s.GreetingServer(port);
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
Client:
public class Client
{
private static String serverName;
public static void main(String [] args)
{
String sName = "192.168.xxxx.x";
int port = 9001;
try
{
System.out.println("Connecting to " + sName
+ " on port " + port);
Socket client = new Socket(sName, port);
System.out.println("Connected");
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("Hello from " + client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
client.close();
}catch(IOException e)
{
}
}
}
What could be the problem? Please me..
Thanks in advance..

Categories

Resources