I have a C# WPF application that uses TCPListener to start a Server in my computer, and an android app that works as a client. It works perfectly when I start the server and emulate the app in my computer, but most of the time it just doesn't work when I use my smartphone to connect to my computer, it only works some times after I restarted my router DHCP and my smartphone.
If you need, here's the connection code
Server:
private static IPAddress ipAd;
private static TcpListener server;
private static TcpClient client;
public static void start() {
//Already tried with both
ipAd = IPAddress.Parse(TCPServer.GetLocalIPAddress());
//ipAd = IPAddress.Parse("127.0.0.1");
server = new TcpListener(ipAd, 1209);
client = default(TcpClient);
try {
server.Start();
Console.WriteLine("Server started");
} catch {
Console.WriteLine("Failed to start server");
}
Client:
Socket socket = null;
String response = new String();
try{
//connect This ipAddress is the same in my desktop
InetAddress ipAd = InetAddress.getByName(ipAddress);
socket = new Socket(ipAd, 1209);
//send
DataOutputStream DOS = new DataOutputStream(socket.getOutputStream());
DOS.write(message.getBytes());
}
...
Thanks for your time, I've should had dedicated more to my Computer Networks class...
Should I redirect some specific port? Have some specific configurations in my router/firewall? I think I'm missing something
This would work when your devices located in the same network in terms of IP routing. However even part of the most simple SOHO grade WiFi routers/AP enable so called device isolation, denying access from wifi devices in the network access between them or to clients, connected with ethernet.
To make this setup work reliably you need to ensure the following:
Use external address of your router in the mobile application. (You can discover it browsing http://whatismyip.org from the server)
Setup port forwarding in your router for particular port to particular IP in your internal network.
As for privided source code, you'd rather use 0.0.0.0 as bind address in the server app, because default .NET implementation will select first available IP address and it may be not the one you're using for connection in the mobile app or not related to the same network. This approach may have security and convenience (coexistence) problems in case of complex networking setup, but will work good for most of the cases.
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.
I am writing a server which uses a DatagramChannel (non-blocking) to send/receive data. It works flawlessly on my local network, but if I try to connect to it using the client application from a different network (i.e. over the internet), I cannot reach it.
Whilst running, if I use http://ping.eu/port-chk/ to check the port, it says it's closed. I have forwarded the appropriate ports and adjusted firewalls to appropriate levels.
My code is as follows:
public void runServer(int portNo)
{
try
{
serverChannel = DatagramChannel.open();
ipAddress = InetAddress.getLocalHost();
//ipAddress = InetAddress.getByName(getPublicIP());
//serverChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true); //Added in to try to fix
serverChannel.socket().bind(new InetSocketAddress(portNo));
serverChannel.configureBlocking(false);
serverChannel.socket().setReceiveBufferSize(receiveBufferSize);
serverChannel.socket().setSendBufferSize(sendBufferSize);
//serverChannel.connect(new InetSocketAddress(ipAddress,portNo)); //Added in to try to fix
serverRunning = true;
}
catch(IOException e)
{
e.printStackTrace();
}
}
The parts which are commented out have had no effect. The ipAddress variable in the example will fetch the local IP, where as the commented-out version will get the public IP of the computer.
If you could help me find out why I cannot connect to this port over the internet, I would be very grateful.
You haven't forwarded the ports correctly. Nothing to do with the code.
As #EJP has suggested, there doesn't seem to be anything wrong with my code. I have since hosted this server application using Amazon EC2, and it has worked flawlessly.
There is an issue with the firmware of my router which is preventing port forwarding.
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 am trying to setup at ServerSocket on my Android phone, and send a char or int or anything from my computer.
The code on the phone creates a ServerSocket and then blocks whilst waiting for a connection:
ServerSocket serverSocket = ServerSocketFactory.getDefault()
.createServerSocket(4444);
Log.d("HostThread", "ServerSocket created:"+serverSocket
.getInetAddress().getHostAddress());
Socket socket = serverSocket.accept();
(The log says "10-27 11:41:43.437: DEBUG/HostThread(23957): ServerSocket created:0.0.0.0")
A simple bit of code running on my PC tries to connect to the phone:
Socket s = new Socket("xx.xx.xx.xx", 4444);
... (plus some more bits if the socket is created. But I'm not getting this point, so left that out!)
Basically, the phone is getting to accept, and the computer is not connecting. The xx.xx.xx.xx is the public IP of the phone I obtain programatically (and it matches up with checking on whatismyip.com).
I have set the INTERNET permission on the phone. I have also been able to do this in reverse (ServerSocket on pc, client on phone).
Any ideas where I am going wrong?
Are you running this in the emulator or on a real device? As far as I understand, most operators networks are NATed and doesn't allow connections to devices. This may be your problem, if you're running on a real device.
However, if your code above is just an example - and you actually don't use port 4444, you should also be aware of that most unix systems (including Android) won't allow incoming connections on ports lower than 1024, unless you have root permissions.