ServerSocket.getLocalSocketAddress() returning empty - java

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?

Related

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!

java server send printstream to port 80 or 443

I have a file transfer applet, and I am at the moment creating a logging system, so in the applet as it initialized, until it send file and finish will start printing a log file (originally it goes to java console on the client side) but now I'm modifying it so it will go to the server instead (create a file in the server and start writing on the file).
It working now, I'm using port 5000, but I need to open the firewall for port 5000 since opening port is dangerous, can I just use port 80 or 443 (HTTPS) since it open anyway for file transfer? how to do it?
example of the code at the moment is
in java applet there will be
handler = new SocketHandler("xxx.xxx.xxx.xx", 5000);
//on different area of the file there will be something like
log("starting the applet");
log("sending email");
...
while on the server I create a simple java server like this
public class ThreadedEchoServer {
// using port 5000
static final int PORT = 5000;
public static void main(String args[]) {
ServerSocket serverSocket = null;
Socket socket = null;
try {
serverSocket = new ServerSocket(PORT);
} catch (IOException e) {
e.printStackTrace();
}
while (true) {
try {
socket = serverSocket.accept();
} catch (IOException e) {
System.out.println("I/O error: " + e);
}
// new thread for a client
new EchoThread(socket).start();
}
}
}
You really should not think about using ports 80 and 443 - these are ports for RECEIVING connections. After a connection is picked up on one of these ports the request is actually redirected to another port for handling. Therefore, using them to write will block any incoming communications.
It working now, I'm using port 5000, but I need to open the firewall
for port 5000 since opening port is dangerous, can I just use port 80
or 443 (HTTPS)? how to do it?
Opening port 5000 is no more dangerouse than opening port 80 or 443. (Changing ports is no more difficult than modifying the numbers, and have no more effect).
I would use the 5000 port and config a chrooted environment if your server is running other important applications.
You could check this thread: What's the best way to defend against a path traversal attack?

How to send datagram packet through Internet?

I'm trying to make a basic datagram client/server program with Java.
I've made the server cling to port 9321 on my local computer.
I've made the client on port 9320 on my local computer,
then send the data over wireless router network (192.168.1.100) at port 9321
the program works!
then i try to send the packet over (via router)internet IP 139.195.12.183(my ip) at port 9321
but it didnt work!
there is this exception:
java.net.SocketException: Interrupted function call: Datagram send failed
i've set the router to forward any request for port 9321 to my computer
and then i've set exception for the firewall on my computer on that port
this is the source
String SERVER = "139.195.12.183";
sendString(SERVER, 9321, "Greetings"); <<
private void sendString(String IP, int port, String toSend) {
byte[] buf = toSend.getBytes();
DatagramPacket packet = null;
try {
packet = new DatagramPacket(buf, buf.length, InetAddress.getByName(SERVER), port);
ds.send(packet);<<
}catch(UnknownHostException e) {
System.out.println("unknownhostception");
}catch(IOException e) {
System.err.println("ioception "+e.getMessage());
}
}
i've had another answers from another forum it said:
"The way routers work, you can't see your external (WAN) internet address from your
internal network (LAN). If that's what you are trying to do, there's nothing wrong, it
just won't work.
Ian."
any explanation?
Some steps that you can take:
Check that the code works across two machines on your LAN.
Check that ping <target-ip> works on your machine.
If it does, check your local and LAN firewall settings for blocking on the port/protocol.
If the ports are unblocked change the port to something else. Some ISPs will block certain ports.
Some more reasons why this error could come up:
UDP (I Assume?) datagram too large.
Client side error that doesn't affect reception (Have seen similar things with some network stacks where the error was spurious.)
Post a link to your code from patsebin or something if you want more info.

Java socket blocks on connection to a server

I am trying to connect to server using a Java socket. I am trying to connect from port 80 to 90
int port;
Socket clientsocket;
String hostname = "www.google.com";
for(port = 80;port<=90; port++){
try{
clientsocket = new Socket(hostname,port);
System.out.println("Connection at port " + port + "\t" + clientsocket.isConnected());
clientsocket.close();
}
catch(Exception e){
System.out.println(e.getMessage());
}
}
When I try to connect to any website like google.com or w3schools.com my program hangs on the socket() call for port numbers except 80.
Since those websites are not serving on ports 81-90 it should raise exception but instead it gets blocked. For port 80 it works fine.
When I try to connect to the apache server installed on my machine, it doesn't block for any port number and gives me Connection refused error which is the obvious behavior.
So why is it happening. Thanks in advance.
When I try to connect to any website like google.com or w3schools.com my program hangs on the socket() call for port numbers except 80. Since those websites are not serving on ports 81-90 it should raise exception but instead it gets blocked.
This is almost certainly not Java's doing.
When you invoke the Socket(String, int) constructor, the JVM asks the OS to attempt to establish a connection to the IP address corresponding to the supplied name, using the supplied port number. Assuming that we're talking TCP/IP, the OS sends off a TCP 'SYN' message, and waits for a response:
If the response is a 'SYN-ACK', it proceeds to establish the connection as per the protocol; see http://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_establishment.
If the response is an 'RST' (reset), the connect fails and this results in a Java "connection refused" exception. (This is typically what happens if the 'SYN' makes it to the remote server, only to discover that there is no application "listening" on the port you tried to connect on.)
If the response is an ICMP message of some kind (e.g. ICMP destination unreachable), this typically results in an immediate failure of the connection request, and a Java exception.
If there is no response, the OS tries again, and again, and again. Depending on the Java default connect timeout (or the explicit timeout), this process could continue for a long time.
So what is most likely happening is that something is filtering the 'SYN' messages on funky ports, and simply throwing them away. It could be the local firewall software on your PC, firewall software in your gateway, or your ISP's network, or software in the remote system you are attempting to talk to. Or this could be happening to the 'SYN-ACK' message coming back.
Either way, the blocking / timeout behavior is inherent to TCP/IP networking, and it is impossible to accurately diagnose at either the OS or Java levels. You simply need to adjust your expectations. (Or set a shorter connect timeout ...)
For this case, and any case:
/**
* Create end point and initialize connection with custom timeout for refused or server offline
*/
try{
InetSocketAddress endPoint = new InetSocketAddress(serverAddress, portNumber);
Socket socket = new Socket();
socket.connect(endPoint, 10000);
} catch(Exception e){
//... Handle connection error
}

Java: Forwarding a port to ServerSocket

I'm building a simple server application, and I can connect to it in the Local Network. But I can't connect over the internet.
This is my Server code:
ServerSocket server;
try {
server = new ServerSocket(4000);
} catch(IOException ex) {
System.out.printf("Could not bind socket 4000\n");
System.exit(1);
}
try {
Socket socket = server.accept();
ClientThread client = new ClientThread(socket);
client.start();
} catch(IOException ex) {
}
And this is the client:
try {
System.out.printf("connecting...\n");
Socket socket = new Socket("mydomain.org", 4000);
System.out.printf("connected!\n");
} catch(UnknownHostException ex) {
ex.printStackTrace();
} catch(IOException ex) {
ex.printStackTrace();
}
I've forwarded port 4000 on my router, which should work. I've forwarded other ports before like 80 and 22.
When I run the client, I get the "connecting..." string, and it hangs there. I don't get "connected!", or a stack trace. But like I said before, it does work on the local network. It works when connecting to 127.0.0.1 and when using 192.168.1.90.
I used CanYouSeeMe.org to check if the port was open. It was successful on port 80, but it times out on 4000.
Check which ip address port 4000 is bound to. It may only be bound to the loopback address (127.0.0.1) instead of any interface.
Not sure which os you're using, but to check:
linux: netstat -ant
windows and mac: netstat -anp tcp
look for the LISTEN line on port 4000 and see whether it's bound to all interfaces (*:4000 or 0.0.0.0:4000), or to a specific interface (127.0.0.1:4000).
If it's not listening on all interfaces, that's your issue - use the constructor that lets you specify the BindAddress.
You've done the experiments to prove that it is not your java and must therefore be a firewall or firewalls issue. Even if you are properly forwarding the ports to your server, the server firewall may not be allowing inbound connections, so check that also.
You have a firewall rule that's throwing away the incoming packets. That's why your client hangs. Check the IP rules on the server computer and on any gateway system to the outside world.

Categories