Java NIO multiple socket connections failing - java

I have a program that attempts to connect to port 80 on different machines and reports if there is a server running. I am using NIO which therefore uses sockets to do the connection. I do a connect and then poll using finishConnect().
I am getting inconsistent behaviour. Sometimes the program correctly reports that there are web servers running on the various machines that I am scanning. However at other times the connections do not get reported even though there are webservers running on the target machines.
I would understand this if I was using UDP sockets as these are not reliable but I am using a TCP connection that should be reliable i.e no dropped packets.
I need to be able to scan many machines but this inconsistent behaviour exhibits it self even when testing the program with just 4 target IP addresses that all have webservers on port 80.
TIA
Rod
class SiteFinder {
private static final long TIMEOUT = 500;
public void findSites() {
int numSocketChannels = 100;
int socketChannelCounter = 0;
long ipAddressCounter = 0;
boolean done = false;
List<String> allIpAddresses =
IPAddressGenerator.getIPAddresses(170);
SocketChannel[] socketChannelArray =
new SocketChannel[numSocketChannels];
Iterator<String> itr = allIpAddresses.iterator();
while(itr.hasNext()) {
int k;
for (k = 0; k < numSocketChannels && itr.hasNext(); k++) {
String ipAddress = itr.next();
ipAddressCounter++;
if (ipAddressCounter % 50000 == 0)
System.out.println(ipAddressCounter + " at " + new Date());
try {
socketChannelArray[k] = SocketChannel.open();
socketChannelArray[k].configureBlocking(false);
if (socketChannelArray[k].connect(
new InetSocketAddress(ipAddress,80))) {
System.out.println(
"connection established after connect() "
+ ipAddress);
socketChannelArray[k].close();
socketChannelArray[k] = null;
}
} catch (IOException ioe) {
System.out.println(
"error opening/connecting socket channel " + ioe);
socketChannelArray[k] = null;
}
}
while (k < numSocketChannels) {
socketChannelArray[k++] = null;
}
long startTime = System.currentTimeMillis();
long timeout = startTime + TIMEOUT;
connect:
while (System.currentTimeMillis() < timeout) {
//System.out.println("passing");
socketChannelCounter = 0;
for(int j = 0; j < socketChannelArray.length; j++) {
//System.out.println("calling finish connect");
if (socketChannelArray[j] == null) {
++socketChannelCounter;
if (socketChannelCounter == numSocketChannels) {
System.out.println("terminating connection loop");
break connect;
}
continue;
}
try {
if (socketChannelArray[j].finishConnect()) {
/*try {
out.write("connection established after " +
finishConnect()" +
clientChannelVector.elementAt(j).socket().
getInetAddress() + '\n');
out.flush();
} catch (IOException ioe) {
System.out.println(
"error writing to site-list "
+ ioe.getMessage());
}*/
System.out.println(
"connection established after finishConnect()"
+ socketChannelArray[j].socket().
getInetAddress());
socketChannelArray[j].close();
socketChannelArray[j] = null;
}
} catch (IOException ioe) {
System.out.println(
"error connecting from "
+ "clientChannel.finishConnect()");
try {
socketChannelArray[j].close();
} catch (IOException e) {
System.out.println("error closing socket channel");
} finally {
//System.out.println("removing socket channel");
//System.out.println(clientChannelVector.size());
socketChannelArray[j] = null;
}
}
}
}
closeConnections(socketChannelArray);
}
}
private void closeConnections(SocketChannel[] socketChannelArray) {
for (int i = 0; i < socketChannelArray.length; i++) {
if (socketChannelArray[i] == null) {
continue;
}
try {
socketChannelArray[i].close();
//System.out.println(
//"TIME OUT WAITING FOR RESPONSE CLOSING CONNECTION");
} catch (IOException ioe) {
System.out.println(
"error closing socket channel " + ioe.getMessage());
}
}
}
}

Related

What is the problem of this code...? Java socket programming

I am coding client-server multithread calculator using java, socket programming.
There's any syntax error, but msgs cannot be received from server.
I think
receiveString = inFromServer.readLine()
does not works. This code is in Client program, in the while(true) loop.
What is the problem?
Here is my full code.
SERVER
import java.io.*;
import java.net.*;
public class Server implements Runnable
{
static int max = 5; //maximum thread's number
static int i = 0, count = 0; //i for for-loop, count for count number of threads
public static void main(String args[]) throws IOException
{
ServerSocket serverSocket = new ServerSocket(6789); //open new socket
File file = new File("src/serverinfo.dat"); //make data file to save server info.
System.out.println("Maximum 5 users can be supported.\nWaiting...");
for(i=0; i <= max; i++) { new Connection(serverSocket); } //make sockets - loop for max(=5) times
try //server information file writing
{
String dataString = "Max thread = 5\nServer IP = 127.0.0.1\nServer socket = 6789\n";
#SuppressWarnings("resource")
FileWriter dataFile = new FileWriter(file);
dataFile.write(dataString);
}
catch(FileNotFoundException e) { e.printStackTrace(); }
catch(IOException e) { e.printStackTrace(); }
}
static class Connection extends Thread
{
private ServerSocket serverSocket;
public Connection(ServerSocket serverSock)
{
this.serverSocket = serverSock;
start();
}
public void run()
{
Socket acceptSocket = null;
BufferedReader inFromClient = null;
DataOutputStream msgToClient = null;
String receiveString = null;
String result = "", sys_msg = "";
try
{
while(true)
{
acceptSocket = serverSocket.accept(); // 접속수락 소켓
count++;
inFromClient = new BufferedReader(new InputStreamReader(acceptSocket.getInputStream()));
msgToClient = new DataOutputStream(acceptSocket.getOutputStream());
System.out.println(count + "th client connected: " + acceptSocket.getInetAddress().getHostName() + " " + count + "/" + max);
System.out.println("Waiting response...");
while(true)
{
if (count >= max+1) // if 6th client tries to access
{
System.out.println("Server is too busy. " + max + " clients are already connected. Client access denied.");
sys_msg = "DENIED";
msgToClient.writeBytes(sys_msg);
acceptSocket.close();
count--;
break;
}
try{ msgToClient.writeBytes(result); }
catch(Exception e) {}
try{ receiveString = inFromClient.readLine(); }
catch(Exception e) // if receiveString = null
{
System.out.println("Connection Close");
count--;
break;
}
System.out.println("Input from client : " + receiveString);
try
{
if(receiveString.indexOf("+") != -1) { result = cal("+", receiveString); }
else if(receiveString.indexOf("-") != -1) { result = cal("-", receiveString); }
else if(receiveString.indexOf("/") != -1) { result = cal("/", receiveString); }
else if(receiveString.indexOf("*") != -1) { result = cal("*", receiveString); }
else if(receiveString.indexOf("+") == -1 || receiveString.indexOf("-") == -1 || receiveString.indexOf("*") == -1 || receiveString.indexOf("/") == -1) { result = "No INPUT or Invalid operation"; }
}
catch(Exception e){ result = "Wrong INPUT"; }
try{ msgToClient.writeBytes(result); }
catch(Exception e) {}
}
}
}
catch(IOException e) { e.printStackTrace(); }
}
}
private static String cal(String op, String recv) //function for calculating
{
double digit1, digit2; //first number, second number
String result = null;
digit1 = Integer.parseInt(recv.substring(0, recv.indexOf(op)).trim());
digit2 = Integer.parseInt(recv.substring(recv.indexOf(op)+1, recv.length()).trim());
if(op.equals("+")) { result = digit1 + " + " + digit2 + " = " + (digit1 + digit2); }
else if(op.equals("-")) { result = digit1 + " - " + digit2 + " = " + (digit1 - digit2); }
else if(op.equals("*")) { result = digit1 + " * " + digit2 + " = " + (digit1 * digit2); }
else if(op.equals("/"))
{
if(digit2 == 0){ result = "ERROR OCCURRED: Cannot be divided by ZERO"; }
else{ result = digit1 + " / " + digit2 + " = " + (digit1 / digit2); }
}
return result;
}
#Override
public void run() {
// TODO Auto-generated method stub
}
}
-----------------------------------------------------------------
CLIENT
import java.io.*;
import java.net.*;
public class Client {
public static void main(String args[]) throws IOException
{
Socket clientSocket = null;
BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));
BufferedReader inFromServer = null;
DataOutputStream msgToServer = null;
String sendString = "", receiveString = "";
try
{
clientSocket = new Socket("127.0.0.1", 6789); //make new clientSocket
inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
msgToServer = new DataOutputStream(clientSocket.getOutputStream());
System.out.println("Input exit to terminate");
System.out.println("Connection Success... Waiting for permission");
while(true)
{
receiveString = inFromServer.readLine();
if(receiveString.equals("DENIED"))
{
System.out.println("Server is full. Try again later.");
break;
}
else { System.out.println("Connection permitted."); }
System.out.print("Input an expression to calculate(ex. 3+1): ");
sendString = userInput.readLine();
if(sendString.equalsIgnoreCase("exit")) //when user input is "exit" -> terminate
{
clientSocket.close();
System.out.println("Program terminated.");
break;
}
try { msgToServer.writeBytes(sendString); }
catch(Exception e) {}
try { receiveString = userInput.readLine(); }
catch(Exception e) {}
System.out.println("Result: " + receiveString); //print result
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
You've set up your server socket stack wrong.
Your code will make 5 threads, each calling accept on a serversocket.
The idea is to have a single ServerSocket (and not 5, as in your example). Then, this single serversocket (running in a single thread that handles incoming sockets flowing out of this serversocket) will call .accept which will block (freeze the thread) until a connection is made, and will then return a Socket object. You'd then spin off a thread to handle the socket object, and go right back to the accept call. If you want to 'pool' (which is not a bad idea), then disassociate the notion of 'handles connections' from 'extends Thread'. For example, implement Runnable instead. Then pre-create the entire pool (for example, 10 threads), have some code that lets you 'grab a thread' from the pool and 'return a thread' to the pool, and now the serversocket thread will, upon accept returning a socket object, grab a thread from the pool (which will block, thus also blocking any incoming clients, if every thread in the pool is already taken out and busy handling a connection), until a thread returns to the pool. Alternatively, the serversocket code checks if the pool is completely drained and if so, will put on a final thread the job of responding to that client 'no can do, we are full right now'.
I'm not sure if you actually want that; just.. make 1 thread per incoming socket is a lot simpler. I wouldn't dive into pool concepts until you really need them, and if you do, I'd look for libraries that help manage them. I think further advice on that goes beyond the scope of this question, so I'll leave the first paragraph as an outlay of how ServerSocket code ought to work, for context.

java opening a socket at wrong ip address [duplicate]

This question already has answers here:
Setting a timeout for socket operations
(6 answers)
Closed 7 years ago.
There are 2 backend machines which will provide the same content. I'm trying to create a round-robin setup and fail-safe so that if one goes down, the request should be sent to other.
As for the round-robin thing, my code is working fine.
For the fail-safe thing, I'm trying to change one IP to some invalid ip (on which no service is running) and then it should connect to other. But it is getting hung up on the line:
client = new Socket(ip, port);
What can be done for this? If I'm not getting connection in 2 seconds, I don't want to retry (if that is what java does, can I reduce the retry timeout?).
Also, after long time, it throws IllegalStateException (I was not expecting it at all)
Here is my constructor for Connect.java:
//Variable declartion
private static int balancer = 0;
private static boolean[] down = {false, false};
private static int[] countDown = {0, 0};
private static final int maxRequests = 10000;
private static int countRequests = 0;
//Constructor
public Connect() throws NullPointerException{
int use = balancer;
int flag = 0;
countRequests = (countRequests + 1) % maxRequests;
if(countRequests == 0){
down[0] = down[1] = false;
}
if((balancer == 0 && down[0] == false) || down[1] == true){
ip = Config.IP1;
port = Config.PORT1;
use = 0;
System.out.println("balancer = 0");
}
else{
ip = Config.IP2;
port = Config.PORT2;
use = 1;
System.out.println("balancer = 1");
}
LOGGER.setLevel(Level.INFO);
// Single simple socket
try {
client = new Socket(ip, port);
System.out.println("client");
dos = new DataOutputStream(client.getOutputStream());
dis = new DataInputStream(client.getInputStream());
if(client == null || dos == null || dis == null){
throw new IOException("Connection could not be opened properly\n");
}
LOGGER.log(Level.INFO, "Connection to : " + ip + " Successfully opened");
balancer = (balancer == 0) ? 1 : 0;
countDown[use] = 0;
flag = 1;
} catch (IOException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
countDown[use] ++;
if(countDown[use] >= 3){
down[use] = true;
}
LOGGER.log(Level.SEVERE, ": " + ip + " " + e.getMessage());
}
finally{ //if connection was not opened on first
if(flag == 0){
if(use == 0){
ip = Config.IP2;
port = Config.PORT2;
use = 1;
}
else{
ip = Config.IP1;
port = Config.PORT1;
use = 0;
}
try {
client = new Socket(ip, port);
dos = new DataOutputStream(client.getOutputStream());
dis = new DataInputStream(client.getInputStream());
if(client == null || dos == null || dis == null){
throw new IOException("Connection could not be opened properly\n");
}
LOGGER.log(Level.INFO, "Connection to " + ip + " Successfully opened");
balancer = (balancer == 0) ? 1 : 0;
countDown[use] = 0;
flag = 1;
} catch (IOException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
countDown[use] ++;
if(countDown[use] >= 3){
down[use] = true;
}
LOGGER.log(Level.SEVERE, ": " + ip + " " + e.getMessage());
throw new NullPointerException("Connection could not be opened properly on both machines\n");
}
}
}
}
What I expected was an IO/NullPointer-Exception and then catch block will be executed
How about using the default Socket() constructor, and then connect(SocketAddress, int), which allows you to specify a specific timeout?
Example:
import java.net.*;
public class Test {
public static void main(String[] args) throws Exception {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(args[0], 80), 2000);
}
}
You can see the timeout in action by timing it:
$ time java Test google.com
real 0m0.154s
user 0m0.079s
sys 0m0.022s
$ time java Test 192.168.2.123
Exception in thread "main" java.net.SocketTimeoutException: connect timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at Test.main(Test.java:5)
real 0m2.111s
user 0m0.076s
sys 0m0.026s

Java - Find Server in network

I want to find my Server in my network, when I don't know the ip.
So that's the code I have, but it takes really (!) long to test all IPs:
for (int j = 1; j < 255; j++) {
for (int i = 1; i < 255; i++) {
String iIPv4 = "192.168." + j + ".";
try {
Socket socket = new Socket();
SocketAddress address = new InetSocketAddress(iIPv4 + i, 2652 );
socket.connect(address, 5);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String fromServer;
while ((fromServer = in.readLine()) != null) {
if (fromServer.equals("Connected to CC3000")) {
System.out.println("CC3000 found! : " + iIPv4 + i);
return iIPv4 + i;
}
}
} catch (UnknownHostException e) {
} catch (IOException e) {
}
}
}
so, whats a better way to find the server?
regards
I think that multithreading could help you here, since you don't want to be waiting for each connection to either establish or fail.
You can try say hundreds of sockets at once instead. Also checking that IP is reachable might save you some time.
Code below is really a naive and horrible example since there's no thread management at all, but you get the picture I hope. You should get the result much faster.
public static void findLanSocket(final int port, final int timeout) {
List<Thread> pool = new ArrayList<>();
for (int j = 1; j < 255; j++) {
for (int i = 1; i < 255; i++) {
final String iIPv4 = "192.168." + j + "." + i;
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("TESTING: " + iIPv4);
try {
// First check if IP is reachable at all.
InetAddress ip = InetAddress.getByName(iIPv4);
if (!ip.isReachable(timeout)) {
return;
}
// Address is reachable -> try connecting to socket.
Socket socket = new Socket();
SocketAddress address = new InetSocketAddress(ip, port);
socket.connect(address, timeout);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String fromServer;
while ((fromServer = in.readLine()) != null) {
if (fromServer.equals("Connected to CC3000")) {
System.out.println("CC3000 found! : " + iIPv4);
}
}
} catch (UnknownHostException e) {
} catch (IOException e) {
}
}
});
pool.add(thread);
thread.start();
}
}
// Wait for threads to die.
for (Thread thread : pool) {
try {
if (thread.isAlive()) {
thread.join();
}
} catch (InterruptedException ex) {
}
}
}

How to check if client has disconnected? [duplicate]

This question already has answers here:
Java detect lost connection [duplicate]
(9 answers)
Java socket API: How to tell if a connection has been closed?
(9 answers)
Closed 9 years ago.
I have a java program with Socket. I need to check if client has disconnected. I need a example how to do that. I have researched but I don't understand. So can someone make example code and explane everything.
sorry for bad English
my code:
package proov_server;
//SERVER 2
import java.io.*;
import java.net.*;
class server2 {
InetAddress[] kasutaja_aadress = new InetAddress[1000];
String newLine = System.getProperty("line.separator");
int kliendiNr = 0;
int kilene_kokku;
server2(int port) {
try {
ServerSocket severi_pistik = new ServerSocket(port);
System.out.println("Server töötab ja kuulab porti " + port + ".");
while (true) {
Socket pistik = severi_pistik.accept();
kliendiNr++;
kasutaja_aadress[kliendiNr] = pistik.getInetAddress();
System.out.println(newLine+"Klient " + kliendiNr + " masinast "
+ kasutaja_aadress[kliendiNr].getHostName() + " (IP:"
+ kasutaja_aadress[kliendiNr].getHostAddress() + ")");
// uue kliendi lõime loomine
KliendiLoim klient = new KliendiLoim(pistik,kliendiNr);
// kliendi lõime käivitamine
klient.start();
}
}
catch (Exception e) {
System.out.println("Serveri erind: " + e);
}
}
DataOutputStream[] väljund = new DataOutputStream[1000];
DataInputStream[] sisend = new DataInputStream[1000];
int klient = 0;
int nr;
// sisemine klass ühendusega tegelemiseks
class KliendiLoim extends Thread {
// kliendi pistik
Socket pistik;
// kliendi number
KliendiLoim(Socket pistik2,int kliendiNr) {
nr = kliendiNr;
this.pistik = pistik2;
}
public boolean kontroll(){
try{
System.out.println("con "+pistik.isConnected());
System.out.println("close "+pistik.isClosed());
if(pistik.isConnected() && !pistik.isClosed()){
//System.out.print(con_klient);
return true;
}
}catch(NullPointerException a){
System.out.println("Sihukest klienti pole!!!");
}
kliendiNr --;
return false;
}
public void run() {
try {
sisend[nr] = new DataInputStream(pistik.getInputStream()); //sisend
väljund[nr] = new DataOutputStream(pistik.getOutputStream()); //väljund
}catch (Exception ea) {
System.out.println(" Tekkis erind: " + ea);
}
while(true){
try{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Sisesta k2sk: ");
String k2sk = null;
k2sk = br.readLine();
/*
String command;
if(k2sk.indexOf(" ") < 0){
command = k2sk;
}else{
command = k2sk.substring(0, k2sk.indexOf(" "));
}
*/
String[] words = k2sk.split("\\s+");
for (int i = 0; i < words.length; i++) {
words[i] = words[i].replaceAll(" ", "");
}
switch(words[0]){
case "suhtle":
if(väljund.length > klient && väljund[klient] != null)
{
väljund[klient].writeUTF("1");
}else{
väljund[klient] = null;
sisend[klient] = null;
System.out.println("Sihukest klienti pole");
}
break;
case "vaheta":
try{
int klinetnr = Integer.parseInt(words[1]);
//if(kontroll(klinetnr) ){
klient = Integer.parseInt(words[1]);
//}
}
catch(NumberFormatException e){
System.out.println("See pole number!!! ");
}
break;
case "kliendid":
if(kliendiNr != 0){
for(int i=1;i <= kliendiNr;i++){
if(kontroll()){
System.out.println("Klient:"+i+" ip: " + kasutaja_aadress[i] );
}else{
System.out.println("Pisi");
väljund[klient] = null;
sisend[klient] = null;
}
}
System.out.println(newLine);
}else{
System.out.println("Kiente pole");
}
break;
}
System.out.println(kliendiNr);
}catch(SocketException a){
System.out.println("Klient kadus");
}
catch(Exception e){
System.out.println(" Viga: " + e);
}
}
}
}
public static void main(String[] args) {
new server2(4321);
}
}
If the client has disconnected properly:
read() will return -1
readLine() returns null
readXXX() for any other X throws EOFException.
The only really reliable way to detect a lost TCP connection is to write to it. Eventually this will throw an IOException: connection reset, but it takes at least two writes due to buffering.
A related thread on Stackoverflow here along with the solution. Basically, the solution says that the best way to detect a client-server disconnect is to attempt to read from the socket. If the read is successfully, then the connection is active.If an exception is thrown during the read there is no connection between the client and the server. Alternatively it may happen that the socket is configured with a timeout value for the read operation to complete. In case, this timeout is exceeded a socket timeout exception will be thrown which can be considered as either the client is disconnected or the network is down.
The post also talks about using the isReachable method - refer InetAddress documentation. However, this method only tells us whether a remote host is reachable or not. This may just one of the reasons for the client to disconnect from the server. You wont be able to detect disconnection due to client crash or termination using this technique.

Java UDP socket client not blocking

I'm trying to code a UDP client to receive packets from a server that is broadcasting on the local network. The problem is the receive method isn't blocking and waiting for a packet to arrive.
Instead, it's receiving null or empty packets.
I've tried to use .setSoTimeout(0), which supposedly will tell the receive to block until it receives a packet, but it doesn't.
Does anyone know how to fix this?
Here's the code:
while (search == true) {
InetAddress addr = InetAddress.getByName("0.0.0.0");
DatagramSocket sock = new DatagramSocket(1355);
sock.setSoTimeout(0);
byte[] recebe = new byte[1024];
sock.setBroadcast(true);
System.out.println("entrou1");
DatagramPacket packet = new DatagramPacket(recebe, recebe.length);
System.out.println("entrou2");
sock.receive(packet);
String info = new String(packet.getData());
System.out.println("tamanho: " + info.length());
if (info.trim().equals("") == false && info != null) {
System.out.println("entrou aqui");
System.out.println("info recebida:" + info + ":fsadfsfs");
String servs[] = info.split("\n");
list1.clear();
servidores.clear();
for (int i = 0; i < servs.length; i++) {
System.out.println("vec: " + servs[i]);
if (servs[i].trim().equals("")) {
System.out.println("break;");
break;
} else {
String aux = servs[i].substring(0, servs[i].lastIndexOf("->"));
System.out.println("aux: " + aux);
list1.add(aux);
servidores.add(servs[i]);
}
}
}
System.out.println("info:\n" + info);
sock.close();
synchronized (obj) {
try {
obj.wait();
} catch (InterruptedException ex) {
Logger.getLogger(AcederPartilhaGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

Categories

Resources