Android Socket Connections - java

Trying to run a loop to check if a IP is open.
for (int z = 0; z < 100; z++) {
String ip = "10.0.0." + z;
try {
log(ip);
Socket socket = new Socket(ip, MainActivity._util.getPort());
// Handle Stuff when Exception NOT throw
} catch (Exception e) {
}
}
log is a function I made (no errors there)
.getPort() is just a "global" port number I've defined
EDIT : That returns 2683 (just a random number)
it is supposed to just catch the exception then move on with the for loop but that doesn't happen.
Currently this just prints:
10.0.0.0
10.0.0.1
and then freezes.
If anyone has any advice that would be great!
EDIT
using socket.connect(new InetSocketAddress(ip, port), timeout) method still didn't handle correctly
This is in an AsyncTask extended class, in the doInBackground() method

There is no socket server to listen those IP and ports. So your socket client will be freeze. As mentioned here you should use another constructor for the socket and set timeout to prevent freezing.
for (int z = 0; z < 100; z++) {
String ip = "10.0.0." + z;
try {
log(ip);
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ip, MainActivity._util.getPort()), 1000);
// Handle Stuff when Exception NOT throw
} catch (Exception e) {
}
}

Related

better way to handle Connection refused when server is down

in Java, using Socket to connect into server with the following code will probably generate an error of java.net.ConnectException: Connection refused: when the server is down or not yet started.
try {
Socket clientSocket = new Socket(SERVER_IP, PORT);
} catch (IOException e) {
e.printStackTrace();
}
what is the best way to handle this exception? how do you continue trying to connect until server become available without having this issue?
UPDATE:
my method is to use UDP, send message into given port and then wait for a response in a given time, loop until I get a response before starting the socket.
I'm looking for a better approach.
What about something along these lines:
String SERVER_IP = "ip";
int PORT = 0;
int maxTries = 10;
int timeBeforeRetry = 5000; //ms
int count = 0;
Socket clientSocket = null;
while(clientSocket == null && count < maxTries) {
try {
clientSocket = new Socket(SERVER_IP, PORT);
} catch(IOException e) {
// Log if you want
try {
Thread.sleep(timeBeforeRetry);
} catch(InterruptedException e) { /* can be ignored or logged I guess */ }
}
count++;
}
if(clientSocket == null) {
// throw some kind of exception
}

What could be causing this socket not to find a port?

I am trying to create a server that receives UDP packets and responds with UDP messages. However, I can't seem to get it to bind to a port. Here's my constructor for the class:
public UDPServer() throws IOException {
myGUI = new ServerGUI();
myClientList = new ArrayList<ClientInfo>();
DatagramChannel channel = DatagramChannel.open();
mySocket = channel.socket();
//mySocket = new DatagramSocket(null);
//mySocket.setReuseAddress(true);
//mySocket.bind(new InetSocketAddress("localhost", Constants.SERVER_PORT_NUM));
myPortNum = mySocket.getPort();
myIP = mySocket.getInetAddress();
System.out.println(myPortNum + " " + myIP.toString());
}
I have tried both the channel method and the commented out method, and I even used this method to try and find an open port:
private DatagramSocket createNewSocket() throws IOException {
for (int i = Constants.MIN_PORT_NUM; i < Constants.MAX_PORT_NUM; i++){
try {
System.out.println(i);
return new DatagramSocket(i);
} catch (IOException e){
continue; // try next port
}
}
throw new IOException("No free port found");
}
But I've had no luck so far. The portNum keeps coming up as -1 and the IP is null. Any ideas what could be going on here?
EDIT: When I run the following in debug mode and scroll over mySocket to see what values it contains, it says that:
bound = true
closed = false
connectedAddress = null
connectedPort = -1
But when I run mySocket.getLocalPort(), it returns a valid port number. What's going on here?
Here's the code:
public UDPServer() throws IOException {
myGUI = new ServerGUI();
myClientList = new ArrayList<ClientInfo>();
mySocket = new DatagramSocket(Constants.SERVER_PORT_NUM);
mySocket.setReuseAddress(true);
myPortNum = mySocket.getLocalPort();
myIP = mySocket.getInetAddress();
System.out.println(mySocket);
}
You don't need to do this. Just create it with the non-args constructor, or specify port zero. The system will allocate a free port for you.

Port still use after DatagramSocket is closed

Following code can reproduce the issue:
int errAt = -1;
try {
System.out.println("start...");
for (int i = 0; i < 4000; i++) {
errAt = i;
DatagramSocket result = new DatagramSocket(null);
result.bind(new InetSocketAddress(InetAddress.getLocalHost(), 9005));
result.close();
//System.out.println(i);
}
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
System.out.println("ErrAt: " + errAt);
e.printStackTrace();
} finally {
System.out.println("end...");
}
In my PC, I'll see "java.net.BindException: Address already in use: Cannot bind" exception after run 2k+ times.
I'm not sure, is this means that the close method didn't close the native socket immediately?
This code works on my Mac even if I set it to run 40,000 iterations. I think the likely problem here is that the socket isn't being closed immediately on Windows but then again you are trying to do thousands of iterations within the space of probably milliseconds.
The following code will continually retry and sleep a small amount of time to let you see if its a delay problem where the socket would be closed within some space of time:
long tCumulative = 0;
int errAt = -1;
System.out.println("start...");
for (int i = 0; i < 4000; i++) {
try {
errAt = i;
DatagramSocket result = new DatagramSocket(null);
result.bind(new InetSocketAddress(InetAddress.getLocalHost(), 9005));
result.close();
//success at last
tCumulative = 0;
} catch (Exception e) {
System.out.println("Error (at="+errAt+") (waited="+tCumulative+"ms): " + e.getMessage());
tCumulative+=50;
Thread.sleep(50);
i--;
}
}
System.out.println("end...");
It is not clear what you are trying to do, but one way to get around the problem of a UDP port still being in use is to set the "reuse address" option before you bind.
Reference: How to set reuse address option for a datagram socket in java code?
If you create the socket but then get e.g. a BindException you aren't closing the socket. It should be closed in a finally {} block.
It is difficult to see the point of this test. Normal UDP programs open one DatagramSocket and leave it open for the life of the process. No sane program would churn through thousands of UDP sockets.

server doesn't receive data from multiple clients (java sockets)

I wrote a simple program where a server should print data sent by multiple clients. But the server receives only partial data. Following are the relevant pieces of the code.
Server:
try {
serverSocket = new ServerSocket(8888);
} catch (IOException e) {
System.err.println("Could not listen on port: 8888");
System.exit(-1);
}
while (listening) {
Socket clientSocket = serverSocket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
System.out.println(reader.readLine());
reader.close();
clientSocket.close();
}
serverSocket.close();
Client:
try {
socket = new Socket("nimbus", 8888);
writer = new PrintWriter(socket.getOutputStream(), true);
localHost = InetAddress.getLocalHost();
}
catch (UnknownHostException e) {}
catch (IOException e) {}
StringBuilder msg1 = new StringBuilder("A: ");
for(int i=1; i<=3; i++)
msg1.append(i).append(' ');
writer.println(localHost.getHostName() + " - " + msg1);
StringBuilder msg2 = new StringBuilder("B: ");
for(int i=4; i<=6; i++)
msg2.append(i).append(' ');
writer.println(localHost.getHostName() + " - " + msg2);
StringBuilder msg3 = new StringBuilder("C: ");
for(int i=7; i<=9; i++)
msg3.append(i).append(' ');
writer.println(localHost.getHostName() + " - " + msg3);
writer.close();
socket.close();
I get the following output (when run on 3 clients)
nimbus2 - A: 1 2 3
nimbus3 - A: 1 2 3
nimbus4 - A: 1 2 3
I don't get the second and third messages. Server keeps waiting. Where am I going wrong?
Edit: In the server code, I tried removing reader.close() and clientSocket.close(). That didn't work either. Another question -- if 3 clients send 3 messages, does it require 9 connections? (this is the reason, I closed the connection in the server code)
You probably want to be delegating the handing of the socket to another thread. I've written up an example that works by passing each incoming socket to an Executor so it can read all the inputs. I use a Executors.newCachedThreadPool() which should grow to be as big as needed. You could also use Executors.newFixedThreadPool(1) if you want it to only be able to handle 1 client at a time.
The only other change I made was I removed the BufferedReader and replaced it with a Scanner. I was having issues with the BufferedReader not returning data. I'm not sure why.
Executor exe = Executors.newCachedThreadPool();
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(8888);
} catch (IOException e) {
System.err.println("Could not listen on port: 8888");
System.exit(-1);
}
while (listening) {
final Socket clientSocket = serverSocket.accept();
exe.execute(new Runnable() {
#Override
public void run() {
try {
Scanner reader = new Scanner(clientSocket.getInputStream());
while(reader.hasNextLine()){
String line = reader.nextLine();
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
serverSocket.close();
It looks like you close the connection to the client before they can finish writing/before the server reads all of the messages they sent. I think you need to continue to readline, and potentially not terminate the client's connection after they send you one message.
John is right.
you close the client connection by calling clientsocket.close() after reading the message that is why you cannot get the other messages. you should call clientsocket.close() when you have received all the messages

cannot get server socket to close

I'm making a simple chat server and just made it so each connection runs on a new thread.
The old version started a single thread for the server, it did a while loop, which would stop when a stop message was sent then close the socket.
The new version loops forever and create a new thread for each new connection. Now I cannot close the socket connection.
If you press a key and the main thread stops, the socket stays open. Thus when I run the program again I need to change the socket number.
code of server
while(true)
{
///////////////////////////////////////////////////
// get a new connection
///////////////////////////////////////////////////
System.out.println("Aceepting connections on port 1030 \r");
try{
// Get New Connection
// wait for ever on accepting new connections
server.setSoTimeout(0);
connection=server.accept();
cConnection thread = new cConnection("thread3", connection);
} catch(IOException ec)
{
System.out.println(ec.getMessage());
}
}
code that starts server
Now each message comes in on a new thread, so I cannot tell it to stop and close the socket.
You need to provide a flag that must be globally accesible, so when some client wants to stop the server then change the variable ans stops the bucle. By example:
class YourServer {
private static boolean execute = true;
public static synchronized void stop() {
execute = false;
}
public void yourMethod() {
while(execute) {
// implement your server here
}
}
}
When a client send the command STOP you must be do
YourServer.stop();
If you want a stop command to stop the server you can call System.exit() to force the program to store or just closing server is likely to be all you need.
Looking into your problem, I understood one thing, that since you are putting
while (true), so your control always gets stuck at connection=server.accept(); listening for a new connection. So in order to stop the sockets you need to first find a way to stop looping in that while loop. Either you can set a Variable, like (int clientsConnected) to check the number of Clients, when that comes to zero stop that while loop. So you can stop your sockets.
Below is my sample code for clients which is doing the same thing for closing the Sockets.
Hopefully this solves your problem.
class GetNamesFromServer implements Runnable
{
private Socket sForName, sForId;
private BufferedReader in, inForName, inForId;
private PrintWriter outForName, outForId;
private static String clientNames;
public GetNamesFromServer(Socket s1, Socket s2)
{
sForName = s1;
sForId = s2;
}
public void run()
{
try
{
outForName = new PrintWriter(sForName.getOutputStream(), true);
outForName.println(Client.clientName);
System.out.println("Send Name : " + Client.clientName);
outForName.flush();
}
catch(IOException e)
{
System.err.println("Error sending Name to the Server.");
}
try
{
inForId = new BufferedReader(new InputStreamReader(sForId.getInputStream()));
Client.clientId = (inForId.readLine()).trim();
System.out.println("Client ID is : " + Client.clientId);
}
catch(IOException e)
{
System.err.println("Error Receiving ID from Server.");
}
try
{
inForName = new BufferedReader(new InputStreamReader(sForName.getInputStream()));
while (true)
{
clientNames = inForName.readLine();
if (clientNames != null && clientNames != "")
{
clientNames = clientNames.substring(1, clientNames.length() - 1);
System.out.println("Names Received : " + clientNames);
String[] names = clientNames.split(", ");
Client.nameClients.clear();
for (String element: names)
Client.nameClients.add(element);
Client.nPane.setText("");
int size = Client.nameClients.size();
System.out.println("Size of list : " + size);
for (int i = 0; i < size; i++)
{
String name = Client.nameClients.get(i);
String colour = Character.toString(name.charAt(0));
name = name.substring(1, name.length()) + "\n";
appendToNamePane(name, ReceiveMessages.getColour(Integer.parseInt(colour)), "Lucida Console");
}
System.out.println("Clients Online : " + Client.nameClients);
}
int index = Client.nameClients.indexOf(Client.clientId + Client.clientName);
**if (index == -1)
{
sForName.close();
break;
}**
}
}
catch(IOException e)
{
System.err.println("Error Receiving Names of Clients from Server");
}
}
NEW EDITION :
You can add a cap to maximum number of clients that can connect, once that reaches your while loop will not go to connection = server.accept(); and hence when they are done chatting (after some time) i.e. totalClients = 0, you can stop your sockets as well, to stop the program.
if (totalClients == 0)
{
socket.close();
serverSocket.close();
}
Regards

Categories

Resources