I need to make a server and client that connects to the server.
Problem: "the server works. the client can only connect to localhost, it cannot connect to a server on the internet. I want the client to connect to the server, via a public ip-address that the server is hosted on."
First of all, I have made sure that the port is forwarded and reachable i have tested the port, secondly i have disabled firewall completely from the server machine.
below is the test code i am using:
The Server: nothing fancy just simple - terminates if a client is connected, else just awaits a connection.
public class Server {
public static void main(String args[]) {
try {
ServerSocket srvr = new ServerSocket(52000);
srvr.accept();
}
catch(Exception e) {
e.printStackTrace();
}
}
}
The Client: I have used no-ip.com to mask the ip of the server to "biogenserver2.noip.me".
Using .getCanonicalHostName(); will return the ip.
public class Client {
public static void main(String args[]) {
try {
String ip = Inet4Address.getByName("somets.noip.com").getCanonicalHostName();
InetSocketAddress sa = new InetSocketAddress(ip, 52000);
//Socket skt = new Socket("0.0.0.0", 52000); //local - this works fine.
Socket skt = new Socket();
skt.connect(sa);
}
catch(Exception e) {
e.printStackTrace();
}
}
}
When i run this the server connects fine, but the client returns a "connection timeout" exception
Any help will be appreciated. Thanks.
Answer:
"Just for clarity: You have checked the port is open via public IP as returned by no-ip and the server will quit without exception when you run that little testclient (on a machine that is not the server machine) - is that correct?" – Fildor
TL:DR
Don't run the client and server on the same machine and the same network trying to connect to your server through your public ip then to your own local network will result in a client timeout exception
I was running the client and server on the same machine and also the same network. This caused the client timeout exception. I tried running the Client on a different machine and a different network and i was able to connect successfully.
What version of IP protocol your application uses? On linux, you may figure it out with netstat -tunap | grep 52000 and watching whether first field is tcp or tcp6. If latter, then it is possible that problem with IPv6 connectivity exists and you may want to prefer using IPv4 to IPv6 by specifying -Djava.net.preferIPv4Stack=true to JVM.
Related
I am using the utility sshuttle to access internet on my computer.
sudo sshuttle --dns -vr user#172.16.30.30 0/0
I have a simple java client server program
Client (My computer running sshuttle)
// client ip is 172.16.23.6
class client {
public static void main(String args[]) {
Socket s = new Socket("172.16.30.20",port); // different server
}
}
The server program, running on 172.16.30.20
class server {
public static void main(String args[]) {
ServerSocket s = new ServerSocket(port);
Socket cl = s.accept();
System.out.println(cl);
}
}
When I run the the server and connect the client, the IP address which the socket cl holds is 172.16.30.30 (IP of server to which I did sshuttle) instead of its own IP which is 172.16.23.6
When I stop sshuttle, the program works fine and the correct IP address is displayed.
I have to run both the programs simultaneously but am unable to do so.
You are out of the luck. sshuttle is like a proxy. The sshuttle server creates completely independent TCP connection from 172.16.30.30 to 172.16.30.20 and it copies incoming data from client connection to this connection. Your server 172.16.30.20 cannot get the information about the real client address because it is present neither in IP nor in TCP header. Your java server is able read sender address from the IP header but it is IP address of host that established the connection and it is 172.16.30.30 (sshuttle server).
Application protocols like HTTP have mechanism how to indicate the real client IP address. HTTP proxy may add HTTP header X-Forwarded-For and server then may learn the client IP from it. But it is possible only if application proxy adds this information to the forwarded data. sshuttle is application protocol independent so it cannot add such information.
Ok so basically I am using KryoNet for the Server-Client communication , and they connect just fine and do what i want them to do in test scenarios. But when i try to connect from a different Network or even a different PC in the same Network the client cant seem to find the Server...
Server
static Server server;
//i dont even send on udp...
static int udpPort = 80, tcpPort = 5190;
public static void main() throws Exception {
System.out.println("Creating the server...");
server = new Server();
server.getKryo().register(SOME.class);
server.bind(new InetSocketAddress(InetAddress.getLocalHost(), tcpPort), new InetSocketAddress(InetAddress.getLocalHost(), udpPort));
server.start();
server.addListener(new ServerProgram());
And the Client
static Client client;
static int udpPort = 80, tcpPort = 5190;
public void connect(String ip) throws InterruptedException {
client = new Client();
client.getKryo().register(SOME.class);
client.addListener(this);
new Thread(client).start();
try {
client.connect(12000, ip, tcpPort, udpPort);
}
catch (IOException e) {
e.printStackTrace();
}
I noticed the Server is always created on my "local" address (192.168.0.***), so is there any way to make the Server more public or do my clients have to use something like Hamatchi ?
You don't have to provide the host address in your server code on Kryonet. Your computer network has its own IP address which is used by Kryonet when you start the server.
So what I mean is rather than doing this
server.bind(new InetSocketAddress(InetAddress.getLocalHost(), tcpPort), new InetSocketAddress(InetAddress.getLocalHost(), udpPort));
You can simply do
server.bind(timeOut, tcpPort, udpPort);
So on client code, when you start the client you put in the IP address (127.0.0.1) in case where both client and server are on same network.
In the case when server and client are on different networks, you need to get the external IP of the computer(network) on which your game server is hosted. Lets say for example your server is hosted on computer(network) with IP 'xxx.x.x.x'. In your client code you will have client.connect(xxx.x.x.x, TCP_PORT_SERVER_LISTENING_ON, UDP_PORT_SERVER_LISTENING_ON)
And on Server
All you have to do on server is server.bind(TIMEOUT, TCP_PORT, UDP_PORT_IF_YOU_USING)
Also if you want to host the server on your computer, you need to do port forwarding.
To find the IP address of the server on which your KryoServer is hosted, you can go to Find IP Address on the server computer, then use this IP address in the client.
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!
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
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.