I have written a simple chat application in Java and its working perfectly fine when i am trying to connect to server using "127.0.0.1" i.e from within the system.
But when i am trying to connect to server using my public ip address,the client is not able to locate socket?How to solve it.
Here is the client code
String ipadd = "213.109.45.23";
InetAddress ip = InetAddress.getByName(ipadd);
sockfd = new Socket(ip,1800);
Here is the server code
String ipadd = "0.0.0.0";
InetAddress ip = InetAddress.getByName(ipadd);
ServerSocket ss = new ServerSocket();
ss.setReuseAddress(true);
ss.bind(new InetSocketAddress(ip,1800));
Related
I am developing a web application which acts as a server. In this application I have implimented ServerSocket for two way communication between server application and wi-fi device which acts as client. I am not connecting to my server directly, I am connecting to my router which port forwards to my system and two way communication is successful. All I want now is to find the MAC address of Wi-fi device which is connected.I have done some research and tried to get the MAC address but failed.Can anyone help me on this.Below is the part of my code.
public class ScheduleJob extends ServletApp implements Job{
private int port = 1717;
public static String number;
String ReceivedData = "";
public void execute(JobExecutionContext context)throws JobExecutionException {
System.out.println("Starting ... ");
ServerSocket Sersocket = null;
System.out.println("Starting the socket server at port:" +port);
boolean listeningSocket = true;
try {
Sersocket = new ServerSocket(port);
System.out.println("Waiting for clients...");
} catch (IOException e) {
System.err.println("Could not listen on port: 1717");
}
try {
while (listeningSocket) {
Socket scokt = Sersocket.accept();
InetAddress MachineAdd = scokt.getInetAddress();
System.out.println("Response-----:" +MachineAdd);
InetAddress ip = InetAddress.getLocalHost();
System.out.println("current ip : "+ip);
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
byte[] mac = network.getHardwareAddress();
System.out.print("Current MAC address : ");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < mac.length; i++) {
sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
}
System.out.println(sb.toString());
MAC address is piece of information which belongs to layer 2 of OSI model.
In other words it's not preserved whenever you are communicating using L3 protocol (until you are communicating directly via cross cable or via L2 switch).
I would recommend you to send MAC address as a part of your application communication from client to your server, so it will not be lost when your router will do port forwarding.
Some of already asked questions on this topic:
Why can't the server get the client MAC address, like the client IP?
How can I get the MAC and the IP address of a connected client in PHP?
how to get a client's MAC address from HttpServlet?
I want that my client application is able to connect to a Server application.
The problem is that my Client doesn't know the Server ip (in LAN).
So I tried to use java object MulticastSocket. Luckily Oracle have a page with an example of Broadcasting.
Here I have rearranged it for my use.
Server code:
long FIVE_SECONDS = 5000;
int port = 4445;
DatagramSocket socket = new DatagramSocket(port);
while (true) {
System.out.println("Server running...");
try {
// message for client
String dString = "Hello Client";
byte[] buf = dString.getBytes();
// send
InetAddress group = InetAddress.getByName("230.0.0.1");
DatagramPacket packet = new DatagramPacket(buf, buf.length, group, port);
socket.send(packet);
// sleep for a while
try {
Thread.sleep((long)(Math.random() * FIVE_SECONDS));
}
catch (InterruptedException e) {
System.err.println("Interrupted Exception");
}
} catch (IOException e) {
System.err.println("IOException");
}
}
Client code:
MulticastSocket socket = new MulticastSocket(4445);
InetAddress address = InetAddress.getByName("230.0.0.1");
socket.joinGroup(address);
// receive the message
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
String received = new String(packet.getData(), 0, packet.getLength());
System.out.println("Received: " + received);
socket.leaveGroup(address);
socket.close();
When I run Srver: no problem, but when I try running client it throw java.net.BindException: Address already in use cause both client and server are listening/sending information on port 4445.
But isn't it right? To connect each other they must have the same port number, or they'll never 'meet'.
Can I solve this problem? How?
Are the port number correct?
Is this a right resolution to the problem about the unknown server ip?
Thanks!
As Warren mentioned in his answer, your client and server can't bind to the same port on the same machine. The Oracle example is not doing that.
The client should bind to port 4446 and the server should bind to port 4445. When the server create a DatagramPacket it should do so with the client's port which is 4446.
If you do this and the client still can't receive, you may need to set the outgoing interface for multicast on the server. You can do this with either the setInterface or setNetworkInterface methods.
For example, suppose your serverhas IP addresses 192.168.1.1 and 192.168.2.1. If you want your sender to send from 192.168.1.1, you would call:
multicastSocket.setInterface(InetAddress.getByName("192.168.1.1"));
You are getting this exception because you are trying to run your server application and your client application on the same machine. When you start your client, your server has already bound to port 4445, so it is already in use - and thus unavailable - when your client tries to bind to it.
Running your server and your client on different machines would get around that particular error. However, you could also get around it by choosing different ports for your server and your client.
For example if you ran your server on port 4445, and your client on port 4446, you could do the following. On the server, you would add a variable for the client port, and use the client port as the destination port when sending your DatagramPacket:
int clientPort = 4446;
...
DatagramPacket packet = new DatagramPacket(buf, buf.length, group, clientPort);
instead of
DatagramPacket packet = new DatagramPacket(buf, buf.length, group, port);
On the client, you would simply bind to the client port instead of the server port:
MulticastSocket socket = new MulticastSocket(4446);
instead of
MulticastSocket socket = new MulticastSocket(4445);
Using different port numbers for the server and for the client would allow you to run both the server application and the client application on the same machine and get you past this particular issue.
I am writing a program with TCP sockets connection between client and server. When the server starts I want to display the IP and port that clients need to use to connect, and when client connects I want the server to show what IP did the client connect from. I am getting confused which command should i use to each of those:
getInetAdress()
getLocalAdress()
getRemoteSocketAdress()
edit
I earlier used int port = 1234 and String IP = "localhost" to test and it worked, but I only used it on one PC, so I think localhost will not work if i start server and client on different computers.
This is server side:
int port = 1234;
...
public void start() {
keepRunning = true;
// create socket
try {
ServerSocket server = new ServerSocket(port);
while (keepRunning) {
display("Waiting for client connections on "
+ server.getInetAddress().getLocalHost()
.getHostAddress() + ":" + port);
Socket conn = server.accept();
if (!keepRunning)
break;
ClientThread t = new ClientThread(conn);
cList.add(t);
t.start();
And this is client:
int port = 1234;
String IP = "localhost";
//these variables can be changed from Client GUI before making connection
...
public boolean start() {
try {
socket = new Socket(IP, port);
} catch (Exception e) {
display("Error connectiong to server:" + e);
return false;
}
try {
sInput = new ObjectInputStream(socket.getInputStream());
sOutput = new ObjectOutputStream(socket.getOutputStream());
} catch (IOException e) {
display("Exception creating new Input/output Streams: " + e);
return false;
}
When i start the server,
display("Waiting for client connections on " + server.getInetAddress().getLocalHost().getHostAddress() + ":" + port);
return this:
Waiting for client connections on 192.168.1.104:1234
which is kind of what i want, but I still cant get it to show me the port. 1234 is a fixed value i used, but I want to use ServerSocket server = new ServerSocket(0); to asign port dynamically, then when i start the client i just put in the values that i got from server and connect.
I tried to use server.getLocalPort() in the display line in server and it returned 55410 or something like that, but when i put this port in client to make connection, it doesn't work. I get Error connectiong to server:java.net.ConnectException: Connection refused: connect. from client
To get the current port that the ServerSocket is listening to, use getLocalPort();
http://download.java.net/jdk7/archive/b123/docs/api/java/net/ServerSocket.html#getLocalPort%28%29
getLocalPort
public int getLocalPort()
Returns the port number on which this socket is listening.
If the socket was bound prior to being closed, then this method will continue to return the port number after the socket is closed.
Edit: Just saw your edit. Are you trying to connect by explicitly referencing the IP and Port? If so, and it's still failing, your server machine might be running a firewall. I'd check for that first.
I'm not familiar with java, and I'm trying to do two Android application that communicates with each other (Client application, and Server application). On Client application, I want to display the Server IP, but it doesn't work with this:
for(i=1;i<=254;i++)
{ s1=partialip+String.valueOf(i);
//partialip has the form: "a.b.c."
//in s1 there are all possible Server's IPs : "192.168.1.1" or "192.168.1.2"...
InetAddress serv = InetAddress.getByName(s1);
Socket socket = new Socket(serv, 5000);
if(socket.isConnected()==true)
{
String server_ip = new String(s1);
text2.setText("Server IP: " + server_ip);
break;
}
}
I will appreciate it if somebody will help me.
To find a server on a local network, you'd better use UDP broadcast (DatagramSocket).
I have a local network with DHCP and a few PCs. One of these should be my Server and get automatically connected to all others (clients). My idea was this:
First, I create a server on every client (CServer) that is listening for a client programm from the server (SClient). When the SClient connects to a CServer, the SClient sends the CServer his IP, so he knows there will be the server on this IP. Then after trying all IPs in his IP range (e.g. 192.168.1.xxx), he starts the real server and all the clients connect to the known server IP.
But when I try the following, the SClient just freezes at the first IP, when trying to connect to 192.168.1.0. How can i define a timeout or something similar that lets the SClient drop the unsuccessful connection and going on with 192.168.1.1?
import java.lang.*;
import java.io.*;
import java.net.*;
class SClient {
public SClient() {
for(int i = 120; i < 125; i++){
try{
InetAddress addr = InetAddress.getLocalHost();
String addrs = addr+"";
String ip = addrs.substring(addrs.indexOf("/")+1);
Socket s1 = new Socket("192.168.1." + i, 1254);
OutputStream s1out = s1.getOutputStream();
DataOutputStream dos = new DataOutputStream (s1out);
dos.writeUTF(ip);
dos.close();
s1out.close();
s1.close();
}catch(IOException e){}
}
}
}
and
import java.lang.*;
import java.io.*;
import java.net.*;
class CServer {
public CServer() throws IOException{
ServerSocket s = new ServerSocket(1254);
while(true){
Socket s1=s.accept();
InputStream s1In = s1.getInputStream();
DataInputStream dis = new DataInputStream(s1In);
String st = new String (dis.readUTF());
System.out.println(st);
dis.close();
s1In.close();
s1.close();
}
}
}
I've found a solution for my problem. It was just initializing the Socket not with
Socket s1 = new Socket("192.168.1." + i, 1254);
but with
Socket s1 = new Socket();
s1.setSoTimeout(200);
s1.connect(new InetSocketAddress("192.168.1." + i, 1254), 200);
Thanks anyway!
It's much easier to do this with UDP. The general logic would be:
Identify a well known port for 'discovery'
Any machine that starts up sends out a 'Query Master Server' message
If a response is not received to that message within a time frame
you define, then the machine that sent it automatically designates
itself as being the server.
Henceforth, any machine that sends out a 'Query Master Server'
message will get a response back from the master, with its IP
address and a 'communication port'
Connect from the new machine to the server on the communication port
and start sending messages.
You might run into situations where more than one server thinks it is the master in this scenario, and then you would need a conflict resolution process, but the outline should give you a general idea of a process that will work for you.