How to create a ServerSocket Object without the localhost address - java

Hy guys, my code here to create a simple server works fine with the local host address(127.0.0.1). Here is my code.
import java.io.*;
import java.net.*;
public class Main {
public static void main(String[] args)
{
Zig z = new Zig();
z.start();
}
}
class Zig
{
ServerSocket ss = null;
InetAddress ia = null;
Socket s = null;
private static final int prt = 56540;
Zig()
{
try
{
byte[] addr = {127,0,0,1};
ia = InetAddress.getByAddress(addr);
SocketAddress sa = new InetSocketAddress(ia,prt);
ss = new ServerSocket();
ss.bind(sa);
s = ss.accept();
}
catch (IOException e)
{
e.printStackTrace();
}
}
Zig start()
{
try
{
InputStream i = s.getInputStream();
InputStreamReader isr = new InputStreamReader(i);
BufferedReader br = new BufferedReader(isr);
String str = null;
while (str != "stp")
{
str = br.readLine();
System.out.println(str);
}
br.close();
isr.close();
i.close();
s.close();
ss.close();
}
catch (IOException e)
{
e.printStackTrace();
}
return this;
}
}
My question is, how can I use the router's IP - 192.168.8.1 instead of 127.0.0.1? I also tried the IP address from http://whatsmyip.org but still got this exception:
java.net.BindException: Cannot assign requested address: JVM_Bind
at java.net.DualStackPlainSocketImpl.bind0(Native Method)
at java.net.DualStackPlainSocketImpl.socketBind(DualStackPlainSocketImpl.java:106)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:387)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:190)
at java.net.ServerSocket.bind(ServerSocket.java:375)
at java.net.ServerSocket.bind(ServerSocket.java:329)
at Zig.<init>(Main.java:26)
at Main.main(Main.java:8)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Exception in thread "main" java.lang.NullPointerException
at Zig.start(Main.java:38)
at Main.main(Main.java:9)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
I wanted to create a simple server with that i can access remotely with another computer both having internet connection.
Or is there a way I can make communication between two computers over internet?
Regards.

how can I use the router's IP - 192.168.8.1
You cannot use the router's IP. You should use the IP thats available in the system.
Note this error :
> java.net.BindException: Cannot assign requested address: JVM_Bind
The bind is failing because the address isn't that of the system.

If you want your 2 devices to communicate via LAN (local network) you can use the addresses your router assigned to these devices (that's the 192.168.8.X address you mentioned. EDIT: As Prabhu mentioned, use the devices IP Address, not the routers IP-Address! You can usually find the IPs your router assigned to connected devices in your routers admin-interface). Remember that your router might assign a different adress to the same devices in the future. Most routers come with a function that always assigns the same IP to a specific device. Also, some routers block communication between local devices (i.e. between wired and WiFi devives) for security reasons. Check your router's configuration for more information and configuration options!
If you want your devices to connect via internet you have to use your routers global IP-address (thats probably the one you found out using whatsmyip).
Additionally, your router usually just blocks incoming requests from the internet for security reasons. Again, your Router probably has a function called Port forwarding, which allows you to redirect requests to a specific device (and a specific port at that device) in your local network. Use this with care, as this opens (a part) of your routers built-in security mechanisms.
Finally, depending on your provider, you may have a IPv4 address (see Wikipedia) that you share with other customers (So called DS-Lite (Wiki). In this case, you're network is not reachable from the IPv4-internet at all and your only chance is to use the IPv6 Protocol (if available).
Hope that helps.

Related

java.net.BindException: Cannot assign requested address (Bind failed) on LinkLocal rebind

I'm writing a Network Framework prototype in Java using UDP to deal with moments where a device using it might not have a permanent and/or reliable connection and how it should deal with it. It is required that I have to be able to use it with "normal" IPv4 and IPv6 addresses as well as IPv6 LinkLocal Addresses.
Due to the concept there's moments where the device loses connectivity and i have to close all DatagramSockets binded to a specific IP/Port pair so i can free resources and, once the device gets a new connection, i need to "rebind" the sockets to the given Addresses.
There's no problems with the code when I'm testing with "normal" IPv4 and IPv6 addresses but once i start using IPv6 LinkLocal addresses I get this exception when I try to rebind a DatagramSocket to any LinkLocal address:
java.net.BindException: Cannot assign requested address (Bind failed)
at java.base/java.net.PlainDatagramSocketImpl.bind0(Native Method)
at java.base/java.net.AbstractPlainDatagramSocketImpl.bind(AbstractPlainDatagramSocketImpl.java:131)
at java.base/java.net.DatagramSocket.bind(DatagramSocket.java:394)
Since this code works for non LinkLocal Addresses i assumed it would work for LinkLocal addresses too.
Here's the code i use to bind a DatagramSocket to a IP/Port pair:
private void bindDatagramSocket() {
try {
this.ds = new DatagramSocket(null);
InetSocketAddress isa = new InetSocketAddress(this.ip, this.port);
this.ds.bind(isa);
this.hasConnection = true;
}
catch (SocketException e) {
e.printStackTrace();
}
Where this.ip and this.port are updated by another Thread that detects a change in the available Addresses and connection status (with/without connection).
When a connection loss is detected I use this code to close the DatagramSocket in use (this.ds)
public void updateConnectionStatus(boolean value){
this.connectionLock.lock();
this.hasConnection = value;
this.connectionLock.unlock();
if(value && !this.isRunning){
new Thread(this).start();
}
else{
if(!value) {
this.ds.close();
this.ds = null;
}
}
Any suggestions are appreciated
TL;DR: Using DatagramSockets to bind to an IP/Port pair corresponding to a IPv6 LinkLocal Address, closing that DatagramSocket and rebinding it to the same IPv6 LinkLocal Address results in Exception even though the same code works for any other case I can test with "normal" IPv4 and IPv6 Addresses

ServerSocket.getLocalSocketAddress() returning empty

I'm trying to create a local server with Wi-Fi P2P between an Android phone and a Raspberry Pi, with the Android as the host. I have been able to successfully establish a P2P connection using wpa_cli on the Pi, but now I am trying to use a C client socket to connect to the phone and transfer data. However, the line Log.d("Socket waiting", serverSocket.getLocalSocketAddress().toString()); spits out D/Socket waiting: ::/:::8888. It doesn't seem to have an address at all, so how am I supposed to connect to it?
As indicated by my comment, my research told me that the correct IP should be 192.168.49.1. If the IP were any different, that would be okay, because I can just send a BLE packet to the phone, telling it the IP. My issue is that the IP is entirely blank.
My code is as follows, for a thread that waits on a connection:
public static class DataTransfer extends Thread {
#Override
public void run() {
Log.d("DataTransfer", "Start");
ServerSocket serverSocket = null;
try {
/**
* Create a server socket and wait for client connections. This
* call blocks until a connection is accepted from a client
*/
// Expects a connection at 192.168.49.1:8888
serverSocket = new ServerSocket(8888);
//serverSocket.setReuseAddress(true);
//serverSocket.toString()
Log.d("Socket waiting", serverSocket.getLocalSocketAddress().toString());
Socket client = serverSocket.accept();
InputStream inputstream = client.getInputStream();
Log.d("InputStream Available", String.valueOf(inputstream.available()));
serverSocket.close();
}
catch (IOException e) {
Log.e("Receive Error", e.getMessage());
if(serverSocket != null) {
try {
serverSocket.close();
} catch (IOException ex) {
Log.e("Failed to close socket", ex.getMessage());
}
}
return;
}
}
}
And here is the output of ip a on the Pi, once it is connected via Wi-Fi P2P
11: p2p-wlan0-8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether b2:0e:07:e6:e6:55 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.23/24 brd 192.168.1.255 scope global noprefixroute p2p-wlan0-8
valid_lft forever preferred_lft forever
inet6 fe80::e79c:33f3:6e49:b6ed/64 scope link
valid_lft forever preferred_lft forever
Final edit:
My problem was seemingly unrelated. As both comments below indicate, the IP shown off is fine, it just means it accepts connections from anything. My actual issue was that I had a static IP set up on my Pi without specifying which interface the static IP was for. The client needed to be on a 192.168.49.# address, and the static IP was preventing it.
You can specify the interface the server socket is listening on by passing an address to the constructor:
serverSocket = new ServerSocket(8888, 10, InetAddress.getByName("192.168.49.1"));
Seeing :: means your server was listening for IPv6 connections on all interfaces. That is represented by the IPv6 address of all zeros which can be written as ::. But you are trying to connect to an IPv4 address, not IPv6. Most systems I've worked with are configured so that IPv4 connections can be accepted by an IPv6 server, but I guess yours isn't. The answer to this question suggests you may be able to change your system's behavior with sysctl:
sysctl net.ipv6.bindv6only=0
:: is the IPv6 default route. It indicates that you are serving requests from all interfaces.
This is the expected behavior. Is there a problem with that?

How to run a simple socket server that allows incoming connections?

I am trying to build a very simple socket server in JAVA that my Flash application can listen to. I am using this tutorial. Everything seems to be working - the JAVA code is compiled and the server is running.
My question is: how can external applications send messages to this server using just an IP address and a port number? My goal is that flash can listen to socket messages sent by an external application.
The Java code:
import java.io.*;
import java.net.*;
class SimpleServer {
private static SimpleServer server;
ServerSocket socket;
Socket incoming;
BufferedReader readerIn;
PrintStream printOut;
public static void main(String[] args) {
int port = 8080;
try {
port = Integer.parseInt(args[0]);
} catch (ArrayIndexOutOfBoundsException e) {
// Catch exception and keep going.
}
server = new SimpleServer(port);
}
private SimpleServer(int port) {
System.out.println(">> Starting SimpleServer");
try {
socket = new ServerSocket(port);
incoming = socket.accept();
readerIn = new BufferedReader(
new InputStreamReader(
incoming.getInputStream()));
printOut = new PrintStream(incoming.getOutputStream());
printOut.println("Enter EXIT to exit.\r");
out("Enter EXIT to exit.\r");
boolean done = false;
while (!done) {
String str = readerIn.readLine();
if (str == null) {
done = true;
} else {
out("Echo: " + str + "\r");
if(str.trim().equals("EXIT"))
done = true;
}
incoming.close();
}
} catch (Exception e) {
System.out.println(e);
}
}
private void out(String str) {
printOut.println(str);
System.out.println(str);
}
}
Maybe I don't understand correctly your problem description, but if you create the server in Java, it listens to its port and not your Flash application. If you want your Flash application to wait for messages from other applications, it must have a server role and listen to a TCP port the same way as this Java server does.
You can connect to and test the given Java server easily by telnet program (available in all operating systems) by providing a host name or an IP address and a port as parameters:
telnet 127.0.0.1 8080
Any other application can connect in a similar way, using just a hostname/IP address and a port. For example in Java, you can create a client socket:
Socket clientSocket = new Socket("localhost", 8080);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
By not specifying an IP address for your socket, it will listen on 0.0.0.0 (all interfaces).
In fact, that will usually be your computer's IP / the server's IP.
Assuming that your application runs on your computer at home, there are three cases that cover most of the connection situations:
Connecting from the same machine:
Use 127.0.0.1:8080
Connecting from the same LAN (e.g. your brother's PC):
Use your LAN IP (e.g. 192.168.1.4:8080)
Connecting from WAN (outside your routers LAN) (internet e.g.):
Use your WAN IP.(e.g. 84.156.74.194). There are plenty websites, that tell you your WAN IP like this
You may have to setup your router, to forward the port 8080 to your PC
For simple connection tests, one could use a telnet client.
I think you are missing the point of client/server socket applications.
If you are building the socket server (with whatever programming language you chose), you will then need to connect with (a) socket client(s) to this server. After a connection is successfully established (persistent) between the client and the server, you can start what ever kind of communication you have implemented between them.
The server always acts as the passive, the client as active part in a socket server/client constellation.
I was checking the link that you are referring to. In that, the procedure to create a stand-alone server is mentioned which is the code that you have pasted as well.
According to the link, the application acts as the client and uses the XMLSocket methods to connect to this server. This application is the flash application that you are talking about. As mentioned in the link, by using the following code any flash application can connect and talk to the server:
var xmlsock:XMLSocket = new XMLSocket();
xmlsock.connect("127.0.0.1", 8080);
xmlsock.send(xmlFormattedData);
When you mention
My goal is that flash can listen to socket messages sent by an external application.
its actually the flash application that is the client and it cannot listen unless programmed to act as a server. I hope this provides some clarity!

Troubleshoot connecting client to server in java

I have been having this problem for some time now and although my efforts and my friends help I can't seem to get past this problem .
My problem is I am trying to establish a connection between client and a server using sockets its very common actually, but for some reason client can't seem to connect to the server don't know why , here is my attempts to solve the problem
1- I used http://portforward.com/ to open the used port on my router which is of type "zhone"
2- I changed the port multiple times and every time I used PFPortChecker to see if my port is open
my code is fairly simple it opens server and when client connects to it , the server sends the date and time
my server code looks like this
public class DateServer {
/** Runs the server. */
public static void main(String[] args) throws IOException {
ServerSocket listener = new ServerSocket(6780);
try {
while (true) {
Socket socket = listener.accept();
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println(new Date().toString());
} finally {
socket.close();
}
}
} finally {
listener.close();
}
}
}
my client code looks like this
public class DateClient {
/** Runs the client as an application. First it displays a dialog box asking for the IP address or hostname of a host running the date server, then connects to it and displays the date that it serves. */
public static void main(String[] args) throws IOException {
//I used my serverAddress is my external ip address
Socket s = new Socket(serverAddress, 6780);
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
String answer = input.readLine();
JOptionPane.showMessageDialog(null, answer);
System.exit(0);
}
}
even though I continued my attempts
3- I closed my firewall just in case
4- I added connection time out in my server socket
with all my attempts I always get this error
Exception in thread "main" java.net.ConnectException: Connection timed out: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at DateClient.main(DateClient.java:13)
note that DateClient.java:13 is this line Socket s = new Socket(serverAddress, 6780);
please help me with this problem , thanks in advance
I tried running your code. First, localhost (127.0.0.1) could solve your problem. On the other side, I changed the ports and IP to my own, and it just works fine (even my external IP). So probably there is something wrong with your port/IP.
In case it works using localhost, your IP was not the right one, or something on your computer is blocking external connections.
Your client code should look like this, for some reason new Socket(String host, int port) wont work.
public class DateClient {
/** Runs the client as an application. First it displays a dialog box asking for the IP address or hostname of a host running the date server, then connects to it and displays the date that it serves. */
public static void main(String[] args) throws IOException {
//I used my serverAddress is my external ip address
InetAddress serverAddress = InetAddress.getByName(String host);
Socket s = new Socket(serverAddress, 6780);
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
String answer = input.readLine();
JOptionPane.showMessageDialog(null, answer);
System.exit(0);
}
}
If it doesn't work using localhost, your port is not forwarded correctly. Try to log in to your router and forward the port from there.
And indeed, like #Audrius Meškauskas said, you might want to close your PrintWriter on your server, right before closing your ServerSockect listener.
Close the PrintWriter on the server side
Be sure you use localhost (try 127.0.0.1) as the server address. Depending on how are you connecting the Internet, the external Internet address (as shown by various "get my ip" tools on the web) may be different from the actual address to that your network interface is configured and not work from the same machine. More here.

Java Networking: Connection refused - Yes, my server is running

I'm getting following error when my client tries to connect to my server socket:
java.net.ConnectException: Connection refused: connect
But, my server is really running, on the same machine. I try to connect to it by using the external IP of my router. But when I try to connect with "localhost", it works. And, yes I did port forwarding correcly in my router. Even canyouseeme.org can connect to my server (The site says: "success" and in my server-log appears that someone connected with the server.)
So, is it for one or another reason impossible to connect to the same machine (or to a machine in the same network) via an external IP? Or is this something typical for Windows? (Normally, I use Linux)
I also tried to completely disable Windows Firewall.
ServerSocket:
public ServerSocket ssocket;
public List<ClientHandler> handlers;
public Server(int port) { // Constructor
try {
ssocket = new ServerSocket(port);
this.handlers = new ArrayList<ClientHandler>();
IpSharingManager.uploadData(Utilities.getPublicIp(), port);
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
Client:
public InvisibleClient(String host, int port) {
try {
System.out.println("Trying to connect to " + host + ":" + port);
this.host = host;
this.socket = new Socket(host, port);
this.bis = new BufferedInputStream(this.socket.getInputStream());
this.bos = new BufferedOutputStream(this.socket.getOutputStream());
this.console = new RemoteConsole(this.socket);
initializeCommunication();
System.out.println("Successfully connected!");
new Thread(this, "Client Thread").start();
} catch (Exception e) {
e.printStackTrace();
System.out.println("No server available");
}
}
Thanks
Some routers doesn't allow the internal network to connect to the external IP address of the router.
You can try to use telnet to connect to your server socket. If telnet isn't able to establish a connection, it's likely a networking problem.
Add the java.exe process and the port to your firewall exception list?
edit: Just read you already tried that. All I can suggest is make sure the network is not blocking that port. (routers)
Have You tried running it with JVM option: java.net.preferIPv4Stack=true ?
For what I see in your code, you missed the part where you accept the conection, after instantiating the server socket you need ssocket.accept() to accept conections and then you have to start reading the outputstrem from the socket

Categories