can't connect Socket when not in same IP range. (subnet) - java

When running a ServerSocket on a machine A with ip 145.74.217.109
And then trying to connect to machine A using machine B with ip 145.74.219.103 I am unable to connect.
But when using machine C with ip 145.74.217.180 it works.
Iam not sure if this is solvable in code or its just network settings. If It is network issues is there another way to go around this problem or would I need to go away from sockets to ...?
Machine A:
public void run() {
try {
sock = new ServerSocket(Constants.PORT);
for (;;) {
Socket newsock = sock.accept();
System.out.println("Accepting new player: ");
new PaintballPlayer(newsock);
}
} catch (Exception e) {
System.out.println("IO error " + e);
}
System.out.println("End!");
try {
sock.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Machine B, C :
socket = new Socket(ip, Constants.PORT);

if you look at the IP us server has IP 145.74.217.109 IP with 145.74.217.180 are able to connect while 145.74.219.103 is not being able to connect it means subnet 145.74.219.X has no access to 145.74.217.X that is why it is not being able to connect. It is network setting ask you network administrator for that. Make your both machine have same subnet mask

Related

Java Client/Server over IPv6

I am trying to get some experience with Java network programming. So I made a simple text based game. This is how it looks on serverside:
try {
socket = new ServerSocket(PORT);
while(true) {
new ConnectedPlayer(socket.accept()).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
And this is the client:
System.setProperty("java.net.preferIPv6Addresses","true");
try {
InetAddress ad = InetAddress.getByName("2a02:8070:b84:6b00:a1d1:30d7:346b:7c14");
socket = new Socket(ad, 9001);
output = socket.getOutputStream();
out = new PrintWriter(output);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
The address above is the Ipv6 address of the machine running
the server, I got this one by a website which detects my IP addresses,
it is different from what I get when I use ipconfig though, tried it with both.
When I tested both on the same machine with localhost, it worked.
However, now I wanted to try it on two different machines, one in a different network. Problem is, my internet provider apparently restricts me to something called "dual stack lite" which means my Server could only be reached over Ipv6 if I understand it correctly. But then, no port forwarding is needed there. When I test it now, it won't connect and gives a timeout after some time. I disabled firewalls on both machines.

TCP Hole Punching and setReuseAddress() on Linux

I am working on a Java client/server application that involves P2P communication over TCP. I'm trying to implement TCP Hole Punching as described here: http://www.brynosaurus.com/pub/net/p2pnat/#sec-tcp. This requires simultaneously listening on and attempting to establish an outgoing connection using the same local TCP port. Apparently, this should work if the SO_REUSEADDR socket option is used, which I am setting via the setReuseAddress() method in Java. However, this is not working as I expected. Here is some test code:
import java.io.IOException;
import java.net.*;
public class Test {
public static void main(String args[]) {
new Thread() {
public void run() {
try {
ServerSocket ss = new ServerSocket();
ss.setReuseAddress(true);
ss.bind(new InetSocketAddress(7077));
ss.accept();
} catch (Exception e) {
System.out.println("ServerSocket exception: " + e.getMessage());
}
}
}.start();
Socket s;
while (true) {
s = new Socket();
try {
s.setReuseAddress(true);
s.bind(new InetSocketAddress(7077));
s.connect(new InetSocketAddress("192.168.0.103", 7077));
break;
} catch (Exception e) {
System.out.println("Socket exception: " + e.getMessage());
try { s.close(); } catch (IOException e1) { }
try { Thread.sleep(1000); } catch (InterruptedException e1) { }
}
}
}
}
This works as expected in Windows 7: the ServerSocket listens on port 7077 in its own thread and the Socket repeatedly attempts to connect to 192.168.0.103:7077. However, under Linux (Ubuntu) only the first Socket connection attempt works, and subsequent attempts get the "Address already in use" BindException. Shouldn't I be able to establish an outgoing connection from a TCP source port that I'm also listening on simultaneously, and to reuse the local port number immediately after closing the socket, since I have the SO_REUSEADDR option enabled?
In Linux, both sockets need to set SO_REUSEADDR socket option. Thus, if we want two sockets, sock1 and sock2 to be bound ot the same port, then s2 would be able to reuse the port/address only if both sock1 and sock2 set SO_REUSEADDR.
You are never closing your client socket, unless there is an exception, making the point of SO_REUSEADDR a no-op.
....
s = new Socket();
try {
// ...
} catch (Exception e) {
System.out.println("Socket exception: " + e.getMessage());
// remove try block from here
try { Thread.sleep(1000); } catch (InterruptedException e1) { }
} finally {
try { s.close(); } catch (IOException e1) { }
}
....
In the above, I moved the closing of the socket to a newly created finally block so it is always executed, even if you break out the global while loop.
Since the socket is now closed under all conditions, the SO_REUSEADDR will use correctly now.

Java Socket on Android, connection through 3G internet global ip

I have problems using Sockets on Android. I'm new to this topic so I try to achieve a simple chat, Android phone to another Android phone as a training.
I can use my code to create a ServerSocket and connect to it with another Socket from the same device ( An 'echo' example with only one client on one device works fine) I've done that also using two IP adresses on the same wifi (192.168...) but any tentative to connect a distant client using internet ip address using 3G connection fails with a
java.net.SocketException: recvfrom failed: ETIMEDOUT (Connection timed out)
What I do is, creating the ServerSocket (ServerConnect.java) :
private ServerSocket _mainServer = null;
private void initServer() {
try {
//port I use here is arbitrary: 8081
_mainServer = new ServerSocket(CONNECT_SOCKET_PORT);
} catch (IOException e) {
Log.w("ServerSocket", e.toString());
e.printStackTrace();
}
}
in the same class, in a separate thread I do this to wait for client connections :
while (running) {
GuestConnect ssc = new GuestConnect(_mainServer.accept());
ssc.setListener(this);
ssc.startConnection();
_clientSockets.add(ssc);
performGuestAdded("bra!");
}
it makes the server waiting for multiple client connection, so it can host more than two poeple in the 'chat room'.
The comunication server side is made from the local client callback and dispatch messages to all my guests (I'm still working on this part, its not really done yet but I don't think its relevant to my problem here) :
public void onMessageReceived(TBTGuestConnect sender, String message) {
for(TBTGuestConnect guestConnect : _clientSockets)
if(guestConnect != sender)
guestConnect.sendMessage(message);
}
Clients are store as 'GuestConnect' objects here is how I set them (GuestConnect.java):
public class GuestConnect {
private StringBuilder _currentMessage;
private BufferedReader _is;
private PrintStream _os;
private Socket _clientSocket = null;
private String _hostname;
private boolean _running = false;
public GuestConnect(String hostname) {
_hostname = hostname;
_currentMessage = new StringBuilder();
}
clientSocket initialisation (still GuestConnect.java):
private void initSocket() {
if(_clientSocket==null)
{
// Try to open a server socket on given port
// Here is the fail when I called it from another device
try {
_clientSocket = new Socket(_hostname, ServerConnect.CONNECT_SOCKET_PORT);
} catch (IOException e) {
Log.w("GuestSocket", e.toString());
}
}
// Create a socket object from the ServerSocket to listen and accept
// connections.
// Open input and output streams
try {
_is = new BufferedReader(new InputStreamReader(_clientSocket.getInputStream()));
_os = new PrintStream(_clientSocket.getOutputStream());
} catch (IOException e) {
Log.w("GuestSocket", e.toString());
}
}
again, in the same class there is the comunication part :
initSocket();
_running = true;
performConnectionStarted();
try {
while (_running) {
String received = _is.readLine();
_currentMessage.append(received);
if (received.contains(ServerConnect.CONNECT_SOCKET_MESSAGE_END)) {
String finalMsg = _currentMessage.toString().substring(0, _currentMessage.lastIndexOf(ServerConnect.CONNECT_SOCKET_MESSAGE_END));
performMessageReceived(finalMsg);
_currentMessage.setLength(0);
}
}
} catch (IOException e) {
Log.w("GuestSocket", e.toString());
performError(e);
} finally {
try {
_os.close();
_is.close();
_clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
performError(e);
}
_clientSocket = null;
}
I can then send a message from this method :
public void sendMessage(String toSend) {
if (_running)
_os.println(toSend+ServerConnect.CONNECT_SOCKET_MESSAGE_END);
else
throw new IllegalStateException("Send message : Connection isn't started !");
}
So the question is, what should I do to make this works using global internet ip addresses ?
And more generally, what it the technical difference between same wifi local ip address and internet ip adress ?
i'll start from the end because it's easier - local ip address is private, it's not valid (and not visible) out of your local network, someone out of your local network can't access it directly but you can access hosts with public ip addresses. because they are not universally visible private addresses are not unique, public ip addresses are unique and (normally) visible from any point on the internet. there's more on the subject http://en.wikipedia.org/wiki/Network_address_translation
when it comes to 3g networks take a look here Could I connect to my iphone using 3g ip? and here ServerSocket accept() not accepting connections on Android . so most probably it can't be done
Don't know if this would be of any importance to you but in our country most 3G accounts are blocked by the ISP from incoming connections. You have to apply to unblock the ports. Some ISP's won't unblock them and some will.
Found that out when I wanted to connect my DVR with a 3G modem.

WiFi network programming in android

i want to program a server/client app in android.
i have one server class on my pc and client on my android phone.
all permissions are ok.
Here is client:
try {
mysocket = new Socket("My PC IP Address", 4444);
} catch (UnknownHostException e) {...
} catch (IOException e) {...
}
here is server:
try {
myServerSocket = new ServerSocket(4444);
} catch (IOException e) {...
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
System.out.println("Connection Established.");
} catch (IOException e) {
}
I uses "Connectify" program on my pc to have an (virtual)access point such that my phone connect to that.
But when I try to connect to server in my android app, it hangs and then throws Timed-out exception.
This code doesn't look bad.
Are you certain Connectify is working well?
You shoud try running both the server and the client you have built on your PC, using two different processes (as an example the server as a standalone and the client in the Android Emulator).
If it works properly from localhost to localhost:4444, the the connection is the cause of the problem, not your code. And otherwise, you will easily find the bug in your code.

Establishing a connection between Java server and client within Android appEDIT

I have an app in android in which I created an android client and a Java sever.
But I'm confronting the following issue: my client (the android part) connects to the local machine on port 6000 using the android loopback address.
My server (in Java) listens on local machine at the port 6000 - but what is the IP I have to use to get the socket that accepts the clients?
InetSocketAddress serverAddr = new InetSocketAddress(SERVERIP,serverPort);
serverSocket = new ServerSocket();
serverSocket.bind(serverAddr);
So what is the SERVERIP I have to use?
UPDATE:My client runns on an emulator!!!!!
EDIT:
public class ClientThread implements Runnable {
Object syncToken;
public ClientThread(Object syncToken) {
this.syncToken = syncToken;
}
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
socket = new Socket(serverAddr, 50458);
} catch (UnknownHostException e) {
System.err.println("Don't know about host");
} catch (IOException e) {
System.err
.println("Couldn't get I/O for the connection to host");
}
try {
out = new PrintStream(socket.getOutputStream());
} catch (IOException e) {
System.out.println(e);
}
while (true) {
synchronized (syncToken) {
try {
syncToken.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
And here is: private String serverIpAddress = "10.0.2.2";!!!!!
From http://developer.android.com/guide/developing/devices/emulator.html#emulatornetworking: if you want to communicate from within the emulator to the local host, use IP 127.0.0.1 on the local host and use IP 10.0.2.2 in Android. This should let you communicate between the Android client and the local host server.
You want to run the server part on the Android? I guess not, and in such case using loopback address is not really going to work, as loopback interface on the Android system loops back to the Android machine itself, it is not routed to the outside.
For the serverAddr, use the #InetSocketAddress(int port) constructor, it specifies the wildcard address and a specific port, meaning it listens on all the interfaces of the machine.
Edit: For best results, on the android device use the DNS name of the server to connect to it.

Categories