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.
Related
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.
I'm writing a piece of UDP networking program (client - server), and I've run into some trouble.
I want to use streams to I/O data, so I googled "udp inputstream" and found UDPInputStream and UDPOutputStream. When I try to use these, however, the program gets stuck when trying to initialize the UDPOutputStream.
This is the line in my code that freezes:
outStream = new UDPOutputStream(InetAddress.getByName("127.0.0.1"), port);
System.out.println("UDP output stream initialized."); // <-- doesn't get called
I checked out the source of the UDPOutputStream, the code gets stuck on this line:
dsock = new DatagramSocket();
Why does the execution hang up on this line? On the server side, I still use my "old", non-stream version of a simple UDP code, and it works. The socket is initialized the same way and it doesn't hang up. I tried to put a port number to the initialization, but it doesn't solve the problem.
Host machines have more than one network interface (for example, 127.0.0.1 for the loopback interface and some other address for the network card; there may be more than one network card).
If you bind to the loopback address 127.0.0.1 then you'll only be able to receive packets sent locally. If want to receive packets sent over the network from a remote machine you must bind to the local IP address (e.g. 192.168.1.100).
Try following:
InetAddress addr = InetAddress.InetAddress.getLocalHost();
outStream = new UDPOutputStream(addr, port);
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
}
For those who do not want to read a long question here is a short version:
A server has an opened socket for a client. The server gets a request to open a socket from
the same client-IP and client-port. I want to fore the server not to refuse such a request but to close the old socket and open a new one. How can I do ti?
And here is a long (original) question:
I have the following situation. There is an established connection between a server and client. Then an external software (Bonjour) says to my client the it does not see the server in the local network. Well, client does nothing about that because of the following reasons:
If Bonjour does not see the server it does not necessarily means that client cannot see the server.
Even if the client trusts the Bonjour and close the socket it does not improve the situation ("to have no open socket" is worser that "to have a potentially bad socket").
So, client do nothing if server becomes invisible to Bonjour. But than the server re-appears in the Bonjour and Bonjour notify the client about that. In this situation the following situations are possible:
The server reappears on a new IP address. So, the client needs to open a new socket to be able to communicate with the server.
The server reappears on the old IP address. In this case we have two subcases:
2.1. The server was restarted (switched off and then switched on). So, it does not remember the old socket (which is still used by the client). So, client needs to close the old socket and open a new one (on the same server-IP address and the same server-port).
2.2. We had a temporal network problem and the server was running the whole time. So, the old socket is still available for the use. In this case the client does not really need to close the old socket and reopen a new one.
But to simplify my life I decide to close and reopen the socket on the client side in any case (in spite on the fact that it is not really needed in the last described situation).
But I can have problems with that solution. If I close the socket on the client side and than try to reopen a socket from the same client-IP and client-port, server will not accept the call for a new socket. The server will think that such a socket already exists.
Can I write the server in such a way, that it does not refuse such calls. For example, if it (the server) sees that a client send a request for a socket from the same client-IP and client-port, it (server) close the available socket, associated with this client-IP and client-port and than it reopens a new socket.
You can't "reopen" a socket on your server. If the socket already exists and the client is trying to reconnect then you should get an BindException (see your previous question). The scenario that may be possible:
Client Shuts down socket
Server OS "notices" socket is dead on client side and shuts its side down
Client reconnects on the same port, but with a "new" socket
In this case you may consider it be the "same" socket, but it really isn't. That said a strategy you may wish to adopt is to have some sort of map (hash of client IP/port) to whatever mechanism you are using to service the socket or some kind of persistent state data, so that it can simulate a continuation of a previous socket (in the same vein as http sessioning). Something along the lines of:
HashMap<Client, State> sessions = ...;
public void server(){
...
while(true){
Socket socket = server.accept();
Client client = new Client(socket);
State s = sessions.get(client);
if(s == null){
s = new State();
sessions.put(client, s);
}
client.setState(s);
service(client);
}
...
}
and you can adjust the map lookup to define what a "session" means within your application (same client IP, same client IP & client port, some sessionid sent over the wire, etc).
If you are just trying to make it possible for the client to reconnect and force the server to "notice" the client is disconnected, the only real way in Java is to try and read/write data, and if it has been shutdown then it should throw an exception. Therefore as was mentioned in your other question you could add some kind of ack/nak feature to your protocol and add some type of check if you believe the client is disconnected (for example if you haven't read any data in the last N milliseconds, send a message the client must echo within M milliseconds, otherwise it is assumed to be disconnected). You can also try isConnected, isInputShutdown, isOutputShutdown, but I have found those to be unreliable in my own code to indicate the socket state, unless you have closed the socket (i.e. the one you are testing on the server).
The situation you describe is impossible. You can't get a new connect request from the same remote IP:port as an existing connection. The client will not permit it to occur.
Based on the comments:
You cannot write the server in a way that it will close a socket it still thinks is connected and automatically accept the new connection, as application code does not have that kind of control over the TCP stack, nor is there a way to reopen a connection.
The chance of the port numbers being the same between your client restarts is very small.
But still, if that happens, the server will note that that you're trying to set up an already connected socket, and refuse your new connection. There's not much else your client can do in this case besides close your socket, create a new one and try to connect again - and another random port will be selected.
additional note, your server should take some form of action to detect and close dead sockets, if all your server does is read incoming data, the "dead" sockets will never be
closed as they will never be detected as dead.(enabling tcp keepalive is one cheap measure to take against dead sockets staying up for months, though it will take a couple of hours to detect them as such by default.)
I have the following problem. My client program monitor for availability of server in the local network (using Bonjour, but it does not rally mater). As soon as a server is "noticed" by the client application, the client tries to create a socket: Socket(serverIP,serverPort);.
At some point the client can loose the server (Bonjour says that server is not visible in the network anymore). So, the client decide to close the socket, because it is not valid anymore.
At some moment the server appears again. So, the client tries to create a new socket associated with this server. But! The server can refuse to create this socket since it (server) has already a socket associated with the client IP and client port. It happens because the socket was closed by the client, not by the server. Can it happen? And if it is the case, how this problem can be solved?
Well, I understand that it is unlikely that the client will try to connect to the server from the same port (client port), since client selects its ports randomly. But it still can happen (just by chance). Right?
Yes, close the socket, as soon as you detect a failure.
The socket will be "stuck" in "close_wait" if not closed properly.
Even if the socket is closed, it's state will be in time_wait for a short period.
However, if You design the application to use a different local port for each new connection, there is no need to wait for the old socket to be closed.
(As you are then creating a completly different socket, since a socket is identified by the remote-ip, remote port, local ip and local port.)
A quick/ dirty illustration of why this can't happen (note the client forcibly uses the same local port in its connection):
public class Server{
public static void main(String[] args) throws Exception {
new Thread(){
java.net.ServerSocket server = new java.net.ServerSocket(12345);
java.util.ArrayList<java.net.Socket> l = new java.util.ArrayList<java.net.Socket>();
public void run() {
try{
while(true){
java.net.Socket client = server.accept();
System.out.println("Connection Accepted: S: "+client.getLocalPort()+", C: "+client.getPort());
l.add(client);
}
}catch(Exception e){e.printStackTrace();}
}
}.start();
}
and a client (replace server address with something valid):
import java.net.InetAddress;
import java.net.Socket;
public class SocketTest {
public static void main(String[] args) throws Exception {
InetAddress server = InetAddress.getByName("192.168.0.256");
InetAddress localhost = InetAddress.getLocalHost();
Socket s = new Socket(server, 12345, localhost, 54321);
System.out.println("Client created socket");
s.close();
s = null;
System.gc();
System.gc();
Thread.sleep(1000);
s = new Socket(server, 12345, localhost, 54321);
System.out.println("Client created second socket");
s.close();
System.exit(55);
}
}
If you start the server and then try to run the client the first connection will succeed, but the second will fail with a "java.net.BindException: Address already in use: connect"
Short answer: yes, you should close socket on both ends.
Although the answer is simple, in reality it may be very hard to detect that the peer has stopped responding if you don't build some ACK/NACK scheme into your client-server protocol.
Even with your protocol ACKs your processing thread may be hanging waiting for ACKs that will never come from the client or vice versa.
If you use Blocking I/O, I would start by setting read timeouts on a socket. Unfortunately, if the peer becomes unresponsive, there is no corresponding time-out for the writes.
One blunt instrument that I found has value in our environment is to create blocking Sockets through java.nio methods and then interrupt the processing thread at configurable intervals.
Interrupting processing thread will close socket, but if you pick the timeout large enough you will know that there is a trouble. We chose this approach because application was written initially with blocking I/O and a cost to transition it to non-blocking was very high.
With the non-blocking I/O, though, you may check at a finer-grained interval the status of your connection and react more intelligently to the slow/unresponsive connections.
Though non-blocking I/O requires a higher upfront investment, I think it will pay better dividends in terms of reliability and better throughput later on.
the client operating system will not allocate the same port to a new socket so soon. there are several mechanism that prevents it. one of which is the TIME_WAIT state that reserves the port for some time after the connection is closed.
I wouldn't worry about it.
if you really need to detect disconnection you will have to implement ping/pong protocol, initiated by both the client and the server.
It sounds like your client is detecting loss of connectivity to the server (using Bonjour), but you don't have the corresponding capability in the other direction.
You're certainly going to want some kind of timeout for inactive connections on the server side as well, otherwise dead connections will hang around forever. Beyond the problem of potential IP address/port # collisions you mention, there's also the fact that the dead connections are consuming OS and application resources (such as open file descriptors)
Conversely, you might also want to consider not being too aggressive in closing a connection from the client side when Bonjour says the service is no longer visible. If you're in a wireless scenario, a transient loss of connectivity isn't that uncommon, and it's possible for a TCP connection to remain open and valid after connectivity is restored (assuming the client still has the same IP address). The optimum strategy depends on what kind of connection you're talking about. If it's a relatively stateless connection where the cost of discarding the connection and retrying is low (like HTTP), then it makes sense to toss the connection at the first sign of trouble. But if it's a long-lived connection with significant user state (like an SSH login session), it makes sense to try harder to keep the connection alive.
If you close server socket only in case of blocking socket then client socket will be closed but not vice versa.
otherwise it would be better socket in both end. Because socket is a heavy weigt for you system. It will use a local port and a remote port of your system forever.
Thanks
Sunil Kumar Sahoo