Can't properly keep track of connected clients java - java

I can't seem to figure out how to notify my Server class that a connection was lost. My server code is:
public class Server {
static int port = 4444;
static boolean listening = true;
static ArrayList<Thread>Clients = new ArrayList<Thread>();
static MatchMaker arena;
public static void main(String[] args) {
Initialize();
Thread startConnections = new Thread(run());
startConnections.start();
}
private static Runnable run(){
System.out.println("(" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + ") Started listening on port: " + port);
try(ServerSocket socket = new ServerSocket(port)){
while(listening){
if(Clients.size() <= 4){
Socket clientSocket = socket.accept();
MultiThread connection = new MultiThread(clientSocket, arena, );
Clients.add(connection);
System.out.println("Client connected from " + clientSocket.getRemoteSocketAddress() + " Assigned ID: " + connection.getId());
System.out.println("Currently connected clients(" + Clients.size() + "): ");
for(int i = 0; i < Clients.size(); i++)
System.out.println(" - " + Clients.get(i).getId());
connection.start();
}
}
}
catch(Exception e){
e.printStackTrace();
}
return null;
}
private static void Initialize(){
arena = new MatchMaker();
}
}
The problem here is that since this class keeps track of the connected clients I want it to notice when a client has lost connection. The MultiThread class already has a functional way of detecting clients that lost connection, however I don't know how to pass that information back to the Server class. I've tried passing the server class to MultiThread as a parameter, but it said I couldn't use 'this' in a static manner.

You can keep them in synchronized map like:
Map<Integer, ClientObject> connectedClients = new HashMap<Integer, ClientObject>(); //key integer will be the client id
Other suggestion:
Map<String, ClientObject> connectedClients = new HashMap<String, ClientObject>(); //key String will be the client IP&userName (you decide)

Fist of all use thread safe collection for monitoring the client connection so replace the following
ArrayList Clients = new ArrayList();
with
ConcurrentLinkedQueue Clients = new ConcurrentLinkedQueue();
But your problem is that you are trying to use limited resource in thread safe manner so best option would be using Semaphore. I have re factored your class a bit to give an idea.Hope it helps. Plz look closely on 'SERVER_INSTANCE'.
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Semaphore;
public class Server {
private final int MAX_AVAILABLE = 4;
public final Semaphore SERVER_INSTANCE = new Semaphore(MAX_AVAILABLE, true);
static int port = 4444;
static volatile boolean listening = true;
static MatchMaker arena;
public static void main(String[] args) {
Initialize();
Thread startConnections = new Thread(run());
startConnections.start();
}
private static void Initialize() {
//do somthing
}
private static Runnable run(){
System.out.println("(" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + ") Started listening on port: " + port);
ServerSocket socket = null;
while(listening){
try {
socket = new ServerSocket(port);
try {
SERVER_INSTANCE.acquire();
Socket clientSocket = socket.accept();
MultiThread connection = new MultiThread(clientSocket, arena, SERVER_INSTANCE);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
return null;
}
static class MultiThread implements Runnable{
Semaphore serverInstance ;
public MultiThread(Socket clientSocket, MatchMaker arena, Semaphore serverInstance) {
serverInstance = serverInstance;
}
#Override
public void run() {
try {
serverInstance.acquire();
//Do your work here
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
serverInstance.release();
}
}
}
class MatchMaker {
}
}

Related

Java: can't close Client connection without closing Server

I made a previous post a bit back working on getting a two-way server/client socket connection working. I've largely succeeded yet, but I still have one more step as a barrier. I'd like to make it so the client disconnects after they perform an operation, but the server remains up and can take in another client operation until the client makes a specific response. I'm attempting to do this through while loops in both the client and server. This is my server class:
import java.net.*;
import java.io.*;
public class ServerDemo {
private Socket mySocket = null;
private ServerSocket server = null;
private static ObjectInputStream in=null;
private static ObjectOutputStream out=null;
private static Payload myPayload=new Payload();
public ServerDemo(int port) throws ClassNotFoundException
{
double time=0;
int bytes=0;
try
{
server = new ServerSocket(port);
System.out.println("Server started");
System.out.println("Waiting for a client ...");
}
catch(IOException i)
{
System.out.println(i);
myPayload.setRepeat(false);
}
try {
while(myPayload.getRepeat()==true) {
mySocket = server.accept();
System.out.println("Client accepted");
in = new ObjectInputStream(
new BufferedInputStream(mySocket.getInputStream()));
out = new ObjectOutputStream(mySocket.getOutputStream());
myPayload.setDataPasses(10);
while (myPayload.getCurr()<myPayload.getDataPasses())
{
try
{
myPayload= (Payload) in.readObject();
myPayload.raisePasses();
out.writeObject(myPayload);
}
catch(IOException i)
{
System.out.println(i);
myPayload.setRepeat(false);
}
}
System.out.println("Closing connection");
mySocket.close();
in.close();
System.out.println("Operation Complete");
System.out.println("Client Address: "+myPayload.getClient());
System.out.println("Server Address: "+myPayload.getServer());
time=System.nanoTime()-(myPayload.getTime());
time=time/1000000000;
System.out.println("Total Time (in seconds): "+time);
bytes=(int) ( ((myPayload.getPacket().length)*myPayload.getDataPasses())/time);
System.out.println("Bytes per Second: "+bytes);
}
}
catch(IOException i)
{
System.out.println(i);
myPayload.setRepeat(false);
}
}
public static void main(String[] args) throws ClassNotFoundException {
// TODO Auto-generated method stub
ServerDemo server=new ServerDemo(5000);
}
}
This is my client class:
import java.net.*;
import java.util.Scanner;
import java.io.*;
public class ClientDemo {
private Socket mySocket = null;
private ObjectInputStream in= null;
private ObjectOutputStream out = null;
private static long roundTrips=1;
private static Payload myPayload=new Payload();
public ClientDemo(String address, int port) throws ClassNotFoundException
{
int packageSize=1;
double time=0;
int bytes=0;
try
{
mySocket = new Socket(address, port);
System.out.println("Connected");
out = new ObjectOutputStream(mySocket.getOutputStream());
in = new ObjectInputStream(new BufferedInputStream(mySocket.getInputStream()));
}
catch(UnknownHostException u)
{
System.out.println(u);
}
catch(IOException i)
{
System.out.println(i);
}
while (myPayload.getCurr()<myPayload.getDataPasses())
{
try
{
if(myPayload.getCurr()==0) {
myPayload.setTime(System.nanoTime());
}
out.writeObject(myPayload);
myPayload= (Payload) in.readObject();
}
catch(IOException i)
{
System.out.println(i);
}
}
try
{
in.close();
out.close();
mySocket.close();
System.out.println("Operation Complete");
System.out.println("Client Address: "+myPayload.getClient());
System.out.println("Server Address: "+myPayload.getServer());
time=System.nanoTime()-(myPayload.getTime());
time=time/1000000000;
System.out.println("Total Time (in seconds): "+time);
bytes=(int) ( ((myPayload.getPacket().length)*myPayload.getDataPasses())/time);
System.out.println("Bytes per Second: "+bytes);
System.out.println("");
}
catch(IOException i)
{
System.out.println(i);
}
}
public static void main(String[] args) throws ClassNotFoundException {
// TODO Auto-generated method stub
boolean isValid=false;
String response="";
int size=16384;
Scanner myScanner = new Scanner(System.in);
ClientDemo client=null;
String server="";
while (size>-1) {
System.out.println("Please enter a max data packet size. Enter -1 to end the program");
while(isValid==false) {
response=myScanner.next();
if(Long.parseLong(response)>=-1 && Long.parseLong(response)<=16384) {
isValid=true;
size=Integer.parseInt(response);
if(size>-1) {
myPayload.setPacket(fillPacket(size));
}
}
else {
System.out.println("Invalid Response. Please enter a value between 1 and 16384.");
}
}
if(size==-1) {
System.out.println("Closing server...");
myPayload.setRepeat(false);
client= new ClientDemo(server, 5000);
}
else {
isValid=false;
System.out.println("Please enter an amount of data passes.");
while(isValid==false) {
response=myScanner.next();
if(Long.parseLong(response)>=1) {
isValid=true;
roundTrips=Long.parseLong(response);
myPayload.setDataPasses(roundTrips);
}
else {
System.out.println("Invalid Response. Please enter a value of 1 or greater.");
}
}
isValid=false;
System.out.println("Please enter your client address.");
response=myScanner.next();
myPayload.setClient(response);
System.out.println("Please enter a server to connect to.");
response=myScanner.next();
server=response;
myPayload.setServer(server);
myPayload.reset();
client= new ClientDemo(server, 5000);
}
}
}
public static int[] fillPacket(int size) {
int[] thePacket= new int[size];
int current=0;
while(current<size) {
for(int counter=0;counter<100;counter++) {
if(current<size) {
thePacket[current]=counter;
current++;
}
}
}
return thePacket;
}
}
When I attempt to run both, the operation I have set up works completely fine, and entering -1 to close the program works but I run into errors when performing operations beyond that. Attempting to set size to -1 to end the program at this point causes an endless loop of
java.io.EOFException
inside ServerDemo, while entering what should be a valid packet size between 0 and 16384 instead produces an endless stream of
java.net.SocketException: Broken pipe (Write failed)
inside ClientDemo. Perhaps most strangely, the latter error only SOMETIMES occurs, not always. If anyone has any pointers on how to get this correctly working and remedying these errors, I would greatly appreciate it!
I would rather change approach. The usual one when doing this kind of stuff is create a thread to listen on your port, then, when a client connects, immediately dispatch the new task to a thread pool and continue listening.
This way not only your server will continue listening after the client disconnects, but also will be able to serve multiple clients in parallel (up to the thread pool size).
Also please use try-with-resources whenever possible to easily avoid resource leaking.
So your code could be changed to something like this:
Server class
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ServerDemo {
private int port;
private Thread listenThread;
private ExecutorService serverPool;
public ServerDemo(int port) {
this.port = port;
}
public synchronized void startServer() {
serverPool = Executors.newFixedThreadPool(4);
listenThread = new Thread(() -> {
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println(String.format("Listening on port %d", port));
System.out.println("1");
while (!Thread.interrupted()) {
System.out.println("2");
Socket clientSocket = serverSocket.accept();
System.out.println("3");
if(!Thread.currentThread().isInterrupted())
serverPool.submit(new ClientTask(clientSocket));
System.out.println("4");
}
} catch (IOException e) {
System.err.println("Error processing client connection");
e.printStackTrace();
}
System.out.println("ListenThread stopped");
}, "ListenThread");
listenThread.start();
}
public synchronized void stopServer() {
System.out.println("Stopping server...");
if (serverPool != null) {
serverPool.shutdown();
serverPool = null;
}
if(listenThread != null) {
listenThread.interrupt();
try (Socket voidSocket = new Socket("localhost", port)) {
// Void socket to unlock the accept() call
} catch (IOException e) {
}
listenThread = null;
}
}
private class ClientTask implements Runnable {
private final Socket clientSocket;
private ClientTask(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
System.out.println("Client accepted");
Payload myPayload = new Payload();
try (ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(clientSocket.getInputStream()));
ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream())) {
myPayload.setDataPasses(10);
while (myPayload.getCurr() < myPayload.getDataPasses()) {
try {
myPayload = (Payload) in.readObject();
myPayload.raisePasses();
out.writeObject(myPayload);
} catch (IOException i) {
System.out.println(i);
break;
} catch (ClassNotFoundException e) {
System.err.println("Error finding class to deserialize");
e.printStackTrace();
}
}
System.out.println("Operation Complete");
System.out.println("Client Address: " + myPayload.getClient());
System.out.println("Server Address: " + myPayload.getServer());
double time = System.nanoTime() - (myPayload.getTime());
time = time / 1000000000;
System.out.println("Total Time (in seconds): " + time);
int bytes = (int) (((myPayload.getPacket().length) * myPayload.getDataPasses()) / time);
System.out.println("Bytes per Second: " + bytes);
} catch (IOException e1) {
System.err.println("Error opening client I/O streams");
e1.printStackTrace();
}
try {
System.out.println("Closing connection");
clientSocket.close();
} catch (IOException e) {
System.err.println("Error closing client connection");
e.printStackTrace();
}
if(!myPayload.getRepeat())
stopServer();
}
}
public static void main(String[] args) throws ClassNotFoundException {
ServerDemo server = new ServerDemo(5000);
server.startServer();
// do other stuff including trapping for sigterm, then call server.stopServer() if needed
}
}
Client class
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class ClientDemo {
private static void executeClientJob(Payload myPayload, int port) {
double time = 0;
int bytes = 0;
try (Socket mySocket = new Socket(myPayload.getServer(), port);
ObjectOutputStream out = new ObjectOutputStream(mySocket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(mySocket.getInputStream()))) {
System.out.println("Connected");
while (myPayload.getCurr() < myPayload.getDataPasses()) {
if (myPayload.getCurr() == 0)
myPayload.setTime(System.nanoTime());
out.writeObject(myPayload);
myPayload = (Payload) in.readObject();
}
System.out.println("Operation Complete");
System.out.println("Client Address: " + myPayload.getClient());
System.out.println("Server Address: " + myPayload.getServer());
time = System.nanoTime() - (myPayload.getTime());
time = time / 1000000000;
System.out.println("Total Time (in seconds): " + time);
bytes = (int) (((myPayload.getPacket().length) * myPayload.getDataPasses()) / time);
System.out.println("Bytes per Second: " + bytes);
System.out.println("");
} catch (UnknownHostException u) {
u.printStackTrace();
} catch (IOException i) {
i.printStackTrace();
} catch (ClassNotFoundException c) {
c.printStackTrace();
}
}
private static void testAutomatic() {
for (int i = 0; i < 1; i++) {
Payload myPayload = new Payload();
myPayload.setPacket(fillPacket(40));
executeClientJob(myPayload, 5000);
}
Payload stopPayload = new Payload();
stopPayload.setRepeat(false);
executeClientJob(stopPayload, 5000);
}
private static void testInteractive() {
Payload myPayload;
boolean repeat;
do {
myPayload = readPayloadSettings();
repeat = myPayload.getRepeat();
executeClientJob(myPayload, 5000);
} while (repeat);
}
private static Payload readPayloadSettings() {
Payload ret = new Payload();
int size = 60;
#SuppressWarnings("resource")
Scanner myScanner = new Scanner(System.in);
System.out.println("Please enter a max data packet size. Enter -1 to end the program");
while (true) {
String response = myScanner.next();
if (Long.parseLong(response) >= -1 && Long.parseLong(response) <= 16384) {
size = Integer.parseInt(response);
break;
} else {
System.out.println("Invalid Response. Please enter a value between 1 and 16384.");
}
}
if (size == -1) {
System.out.println("Closing server...");
ret.setRepeat(false);
} else {
ret.setPacket(fillPacket(size));
System.out.println("Please enter an amount of data passes.");
while (true) {
String response = myScanner.next();
if (Long.parseLong(response) >= 1) {
ret.setDataPasses(Long.parseLong(response));
break;
} else {
System.out.println("Invalid Response. Please enter a value of 1 or greater.");
}
}
System.out.println("Please enter your client address.");
ret.setClient(myScanner.next());
System.out.println("Please enter a server to connect to.");
ret.setServer(myScanner.next());
}
return ret;
}
public static int[] fillPacket(int size) {
int[] thePacket = new int[size];
int current = 0;
while (current < size) {
for (int counter = 0; counter < 100; counter++) {
if (current < size) {
thePacket[current] = counter;
current++;
}
}
}
return thePacket;
}
public static void main(String[] args) throws ClassNotFoundException {
testInteractive();
//testAutomatic();
}
}
Payload class (with defaults to quick create an automatic test)
import java.io.Serializable;
public class Payload implements Serializable {
private int curr=0;
private long dataPasses=5;
private long time;
private String client="localhost";
private String server="localhost";
private int[] packet=new int[0];
private boolean repeat=true;
public Payload() {
}
public int getCurr() {
return curr;
}
public void setCurr(int curr) {
this.curr = curr;
}
public long getDataPasses() {
return dataPasses;
}
public void setDataPasses(long roundTrips) {
this.dataPasses = roundTrips;
}
public long getTime() {
return time;
}
public void setTime(long nanoTime) {
time = nanoTime;
}
public String getClient() {
return client;
}
public void setClient(String client) {
this.client = client;
}
public String getServer() {
return server;
}
public void setServer(String server) {
this.server = server;
}
public int[] getPacket() {
return packet;
}
public void setPacket(int[] packet) {
this.packet = packet;
}
public boolean getRepeat() {
return repeat;
}
public void setRepeat(boolean r) {
this.repeat = r;
}
public void reset() {
curr=0;
dataPasses=0;
}
public void raisePasses() {
curr++;
}
}

When creating a chatServer that sends data using ObjectInput/OutputStreams I get a java.io.StreamCorruptedException: invalid stream header

Good day
This is my first post, because I have no idea what to do :(
I am creating a web application that has 2 functions
It is a Tic Tac Toe multiplayer game.
It is a multiuser chat client.
So after many hours of hard work I got the multiuser chat to work (YAY!!). But the server/client was using strings to send data via PrintWriter and BufferedReader. Now that is all good, but I need (Specs say so) to send XML data through the server for the multiplayer game.
The problem comes in when I change all my PrintWriters and BufferedReaders to ObjectInputStreams and ObjectOutputStreams. I will give code to show where everything takes place.
This is the server's skeleton, which basically creates the ServerSocket then accepts all incoming connections which creates a new ChatHandler Object:
import java.io.*;
import java.net.*;
import java.util.*;
//import javagently.*;
import javax.swing.JOptionPane;
public class ChatServer {
/* The Chatter program by J M Bishop January 1997
* =================== Java 1.1 January 1998
* updated August 2000
*
* Sets up a server for multiple conversations.
*
* Join in by typing
* telnet x y
* where x and y are the computer's name and port as
* given when the Chatter starts.
*
* Illustrates sockets, streams on sockets,
* threads, synchronization and the use of lists (again).
*/
private static LinkedList clientList = new LinkedList();
private static LinkedList clientListNames = new LinkedList();
private static int id = 0;
public static void main(String[] args) throws IOException {
// Get the port and created a socket there.
int port = Integer.parseInt(JOptionPane.showInputDialog("Enter the port"));
if (args.length > 0)
port = Integer.parseInt(args[0]);
new ChatServer (port);
}
class Terminal extends Thread{
public Terminal(){
}
public void run() {
while(true){
String message = JOptionPane.showInputDialog("Enter command");
if(message.equals("xxx")){
printClients();
}
if(message.equals("quit")){
System.exit(0);
}
}
}
}
ChatServer (int port) throws IOException {
//new Terminal().start();
ServerSocket listener = new ServerSocket(port);
System.out.println("The Chat Server is running on port "+port);
// Listen for clients. Start a new handler for each.
// Add each client to the linked list.
while (true) {
Socket client = listener.accept();
new ChatHandler(client).start();
System.out.println("New client no."+id+
" from "+ listener.getInetAddress()+
" on client's port "+client.getPort());
clientList.add(client);
id++;
}
}
synchronized static void broadcast(String message, String name, String type)
throws IOException {
// Sends the message to every client including the sender.
Socket s;
ObjectOutputStream oos;
for (ListIterator list = clientList.listIterator(); list.hasNext();) {
s = (Socket) list.next();
oos = new ObjectOutputStream(s.getOutputStream());
oos.writeChars(type+"#"+name+": "+message);
}
}
synchronized static void sendToPeer(Object message, String name, String type, Socket receiver)
throws IOException {
// Sends the message to every client including the sender.
Socket s = receiver;
ObjectOutputStream oos;
oos = new ObjectOutputStream(s.getOutputStream());
oos.writeChars(type+"#"+name+":"+message);
}
synchronized static Socket getClient(String name){
int pos = clientListNames.indexOf(name);
return (Socket)clientList.get(pos);
}
synchronized static void remove(Socket s, String n) {
/* Using the LinkedList remove method, removes the
* first occurrence of the given socket object
*/
clientList.remove(s);
clientListNames.remove(n);
id--;
}
public static void printClients(){
System.out.println("Printing Clients");
for (int i = 0; i < clientList.size(); i++) {
System.out.println("Client: No"+i);
}
}
public static String getClientNames() {
String names = "";
for (int i = 0; i < clientListNames.size(); i++) {
names = names + "#" + clientListNames.get(i)+"#";
}
return names;
}
public static void addClientName(String cName){
clientListNames.add(cName);
}
}
This is the ChatHandler class, this is where I am getting my error:
import java.io.*;
import java.net.*;
import java.util.Calendar;
class ChatHandler extends Thread {
/* The Chat Handler class is called from the Chat Server:
* one thread for each client coming in to chat.
*/
private ObjectInputStream in;
private ObjectOutputStream out;
private Socket toClient;
private String name;
private boolean inGame= false;
private Socket enemy;
private String enemyName;
ChatHandler(Socket s) {
toClient = s;
}
public void run() {
try {
/* Create i-o streams through the socket we were
* given when the thread was instantiated
* and welcome the new client.
*/
in = new ObjectInputStream(toClient.getInputStream());
out = new ObjectOutputStream(toClient.getOutputStream());
//out.println("*** Welcome to the Chatter ***");
//out.println("Type BYE to end");
//out.println("What is your name? ");
out.flush();
String name = (String) in.readObject();
ChatServer.addClientName(name);
ChatServer.broadcast(name+" has joined the chat room.", "Server ("+getTime()+")","SHOW");
String cNames = ChatServer.getClientNames();
ChatServer.broadcast(cNames,"LISTCLIENTS","NOTSHOW");
// Read lines and send them off for broadcasting.
while (true) {
Object o = in.readObject();
if(o instanceof String){
String s = (String) o;
if (s.equals("BYE")) {
ChatServer.broadcast(name+" has left the discussion.","Server ("+getTime()+")","SHOW");
ChatServer.remove(toClient,name);
toClient.close();
cNames = ChatServer.getClientNames();
ChatServer.broadcast(cNames,"LISTCLIENTS","NOTSHOW");
return;
}
if(s.equals("LISTCLIENTS")){
cNames = ChatServer.getClientNames();
ChatServer.broadcast(cNames,"LISTCLIENTS","NOTSHOW");
ChatServer.broadcast(cNames,"LISTCLIENTS","SHOW");
}if(s.contains("PLAYGAME")){
enemyName = s.substring("PLAYGAME".length());
if(!name.equals(enemyName)){
enemy = ChatServer.getClient(enemyName);
inGame = true;
String xml = createBoard(name, enemyName);
ChatServer.sendToPeer(xml, name, "PLAYWITHME", enemy);
}
}else{
cNames = ChatServer.getClientNames();
ChatServer.broadcast(cNames,"LISTCLIENTS","NOTSHOW");
ChatServer.broadcast(s, name + "("+getTime()+")","SHOW");
}
}
}
}
catch (Exception e) {
System.out.println("Chatter error: "+e.getMessage());
}
}
private String getTime(){
int hours = Calendar.getInstance().getTime().getHours();
String strHours;
if(hours<10){
strHours = "0"+hours;
}else{
strHours = ""+hours;
}
int minutes = Calendar.getInstance().getTime().getMinutes();
String strMinutes;
if(minutes<10){
strMinutes = "0"+minutes;
}else{
strMinutes = ""+minutes;
}
int seconds = Calendar.getInstance().getTime().getSeconds();
String strSeconds;
if(seconds<10){
strSeconds = "0"+seconds;
}else{
strSeconds = ""+seconds;
}
return strHours + ":" + strMinutes + ":" + strSeconds;
}
private String createBoard(String n, String en) {
return null;
}
}
I connect to the Java server through javascript with the help of this neat little applet: Here
I am getting a
"Chatter error: java.io.StreamCorruptedException: invalid stream header: 46616269"
when I reach the line :
"in = new ObjectInputStream(toClient.getInputStream());"
in the ChatHandler class
Any help will be appreciated

Synchronized threads throwing a CurrentModificationException

I am having trouble getting the concurrency running on a simple UDP chat client I am writing, it all works perfectly until I try to add a new contact to the outgoing message list stored in Peer, it throws a CurrentModificationException, can someone help me understand where I have gone wrong?
Here are my classes
import java.net.*;
import java.util.*;
import java.io.*;
public class Chatter {
public static class ReceiveMess extends Thread{
DatagramSocket ds;
public ReceiveMess(DatagramSocket s){
ds = s;
}
byte[] Rbuf = new byte[1000];
DatagramPacket Rdgp = new DatagramPacket(Rbuf, Rbuf.length);
public synchronized void run() {
try{
while (true){
for(Peer p : Peer.PeerList){
ds.receive(Rdgp);
String rcvd = new String(Rdgp.getData(), 0, Rdgp.getLength()) + ", from address: "
+ Rdgp.getAddress() + ", port: " + Rdgp.getPort();
System.out.println(rcvd);
}
}
}
catch(IOException e) {
System.out.println(e);
}
}
}
public static class SendMess extends Thread{
DatagramSocket ds;
public SendMess(DatagramSocket s){
ds = s;
}
int SPORT = 40080;
byte[] Sbuf = new byte[1000];
DatagramPacket Sdgp = new DatagramPacket(Sbuf, Sbuf.length);
public synchronized void run() {
try{
while (true) {
BufferedReader consR = new BufferedReader(new InputStreamReader(System.in));
String MessOut = consR.readLine();
if(MessOut.startsWith("/NEW")){
try{
String[] splitArray = MessOut.split(" ");
String newIP = (splitArray[1]);
Peer p = new Peer(newIP);
System.out.println(newIP + " added to the contacts list");
continue;
}
catch(Exception e){
System.out.println("Please format NEW IP address's as NEW XXX.XXX.XXX.XXX");
continue;
}
}
else{
Sbuf = ("Server Said: " + MessOut).getBytes();
for(Peer p : Peer.PeerList){
DatagramPacket out = new DatagramPacket(Sbuf, Sbuf.length, p.IP, SPORT);
ds.send(out);}
}
}
}
catch(IOException e) {
System.out.println(e);
}
}
}
public static void main(String [] args){
try{
for(String s : args){
String address = s;
Peer peer = new Peer(address);
}
int PORT = 40080;
DatagramSocket ds = new DatagramSocket(PORT);
Peer.PrintList();
SendMess sendmess = new SendMess(ds);
sendmess.start();
ReceiveMess receivemess = new ReceiveMess(ds);
receivemess.start();
}
catch(Exception e){
System.out.println(e);
}
}
}
And my peer class,
import java.net.*;
import java.util.*;
public class Peer{
InetAddress IP;
static List<Peer> PeerList = new LinkedList<Peer>();
Peer(String clientAddress){
try{
IP = IP.getByName(clientAddress);
AddToList(this);
}
catch(UnknownHostException e){
System.out.println(e.toString());
}
}
public synchronized void AddToList(Peer peer){
PeerList.add(this);
}
public List<Peer> GetList(){
return PeerList;
}
public static void PrintList(){
for(Peer p : PeerList){
System.out.println(p.IP.toString());
}
}
}
So your issue is this...
You have a loop in ReceiveMess that iterates the list in Peer. At the same time in SendMess you are creating new instances of Peer. When a new instance of Peer is created this adds a new element to the PeerList. This then causes the CME in ReceiveMess.
What I would suggest is that you remove all the synchronized keywords as they are not doing anything for you and return a COPY of the list from Peer.getList. This means that as one thread is iterating the list, even if the other thread modifies the list of Peers the iterating thread will not be effected. The iterating thread will then see the update on the next iteration of the while loop.
One mechanism to do this is to use a CopyOnWriteArrayList or Guava's ImmutableList.Builder.
CopyOnWriteArrayList
ImmutableList.Builder
The keyword synchronized for a method is equivalent to:
public void run() {
synchronized(this) {
...
}
}
In your synchronized methods, this is a different object (ReceiveMess,SendMess and Peer), so there's nothing stopping those methods from running at the same time. Use a common monitor instead, (Chatter.class is the most expedient).
In other words, synchronized for methods is not global, it's just a shortcut to synchronizing on the monitor of this. I encourage you to read at least this entire track before you continue.

Establishing WebSocket connection with Java server and Javascript client

I'm trying to implement WebSockets with a Javascript-based client and a Java-based server. I think I've done all the correct steps, but for an unknown reason, I can't establish the connection with both.
When the server socket receives a connection, it handles to form a websocket-accept response, and it sends back to the client, but the connection in the client socket instantly close, weird that there's no handshake problem.
Does anyone have an idea what might be the problem?
Here's my server code implemented in java:
package server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import server.message.Message;
import server.message.SpeakMessage;
public class Server implements ConnectionListener {
private static final int PORT = 1509;
private MessageDispatcher dispatcher = new MessageDispatcher();
private List<ConnectionManager> clients = new ArrayList<>();
public void listen() {
try (ServerSocket server = new ServerSocket(PORT)) {
System.out.printf("Listening on port %d...%n", PORT);
while (true) {
System.out.println("Waiting for connection...");
Socket client = server.accept();
System.out.println("Incoming connection - Attempting to establish connection...");
ConnectionManager manager = new ConnectionManager(client, dispatcher, this);
manager.start();
}
} catch (IOException e) {
System.out.println("Unable to start server");
e.printStackTrace();
}
System.exit(0);
}
public void execute() {
try {
while (true) {
if (dispatcher.isEmpty()) {
Thread.sleep(100);
continue;
}
Message msg = dispatcher.read();
if (msg instanceof SpeakMessage)
broadcast(MessageEncoder.spoke(((SpeakMessage) msg).getText()));
}
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
public static void main(String[] args) {
final Server server = new Server();
new Thread(new Runnable() {
#Override
public void run() {
server.listen();
}
}).start();
server.execute();
}
public synchronized void broadcast(byte[] message) {
for (ConnectionManager client : clients) {
client.send(message);
}
}
#Override
public synchronized void clientConnected(ConnectionManager who) {
clients.add(who);
System.out.println("Connected client " + clients.size());
}
#Override
public synchronized void clientDisconnected(ConnectionManager who) {
clients.remove(who);
}
}
Heres subclass ConnectionManager of server:
package server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.Socket;
import java.security.MessageDigest;
import java.util.Properties;
import server.message.HandshakeMessage;
import server.message.Message;
public class ConnectionManager {
private static final int CLIENT_VERSION = 1;
private Socket socket;
private MessageDecoder decoder = new MessageDecoder();
private MessageDispatcher dispatcher;
private ConnectionListener listener;
public ConnectionManager(Socket connection, MessageDispatcher dispatcher, ConnectionListener listener) {
socket = connection;
this.dispatcher = dispatcher;
this.listener = listener;
}
public void start() {
Thread t = new Thread(new ChannelReader());
t.setName("Client thread");
t.setDaemon(true);
t.start();
}
public void send(byte[] data) {
if (socket == null)
return;
try {
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.write(data);
dos.flush();
} catch (IOException e) {
disconnect("Client closed the connection");
}
}
private class ChannelReader implements Runnable {
private boolean accepted = false;
private String ret = null;
#Override
public void run() {
try {
DataInputStream in = new DataInputStream(socket.getInputStream());
while (socket != null && socket.isConnected()) {
int len = in.readShort();
if (len < 0) {
disconnect("Invalid message length.");
}
String s;
readLine(in);
Properties props = new Properties();
while((s=readLine(in)) != null && !s.equals("")) {
String[] q = s.split(": ");
props.put(q[0], q[1]);
}
if(props.get("Upgrade").equals("websocket") && props.get("Sec-WebSocket-Version").equals("13")) { // check if is websocket 8
String key = (String) props.get("Sec-WebSocket-Key");
String r = key + "" + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // magic key
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.reset();
md.update(r.getBytes());
byte[] sha1hash = md.digest();
String returnBase = base64(sha1hash);
ret = "HTTP/1.1 101 Switching Protocols\r\n";
ret+="Upgrade: websocket\r\n";
ret+="Connection: Upgrade\r\n";
ret+="Sec-WebSocket-Accept: "+returnBase;
} else {
disconnect("Client got wrong version of websocket");
}
Message msg = decoder.decode((String) props.get("Sec-WebSocket-Protocol"));
if (!accepted) {
doHandshake(msg);
} else if (dispatcher != null) {
dispatcher.dispatch(msg);
}
}
} catch (Exception e) {
disconnect(e.getMessage());
e.printStackTrace();
}
}
private void doHandshake(Message msg) {
if (!(msg instanceof HandshakeMessage)) {
disconnect("Missing handshake message");
return;
}
HandshakeMessage handshake = (HandshakeMessage) msg;
if (handshake.getVersion() != CLIENT_VERSION) {
disconnect("Client failed in handshake.");
return;
}
send(ret.getBytes());
accepted = true;
listener.clientConnected(ConnectionManager.this);
}
private String base64(byte[] input) throws ClassNotFoundException,
SecurityException, NoSuchMethodException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> c = Class.forName("sun.misc.BASE64Encoder");
java.lang.reflect.Method m = c.getMethod("encode", new Class<?>[]{byte[].class});
String s = (String) m.invoke(c.newInstance(), input);
return s;
}
private String readLine(InputStream in) {
try{
String line = "";
int pread;
int read = 0;
while(true) {
pread = read;
read = in.read();
if(read!=13&&read!=10)
line += (char) read;
if(pread==13&&read==10) break;
}
return line;
}catch(IOException ex){
}
return null;
}
}
public synchronized void disconnect(String message) {
System.err.println(message);
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
}
}
socket = null;
listener.clientDisconnected(ConnectionManager.this);
}
}
And the MessageDispatcher:
package server;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingDeque;
import server.message.Message;
public class MessageDispatcher {
Queue<Message> messageQueue = new LinkedBlockingDeque<>();
public void dispatch(Message message) {
messageQueue.offer(message);
}
public Message read() {
return messageQueue.poll();
}
public boolean isEmpty() {
return messageQueue.isEmpty();
}
}
And heres my client code implemented in javascript:
var canvas, // Canvas DOM element
ctx, // Canvas rendering context
socket; // Socket connection
function init() {
// Initialise the canvas
canvas = document.getElementById("gameCanvas");
ctx = canvas.getContext("2d");
// Maximise the canvas
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Initialise socket connection
if (window.WebSocket) {
socket = new WebSocket("ws://localhost:1509/", ["1", "YURI"]);
socket.onopen = onSocketConnected();
socket.onclose = onSocketDisconnect();
socket.onmessage = onSocketMessage();
socket.onerror = onSocketError();
} else {
alert("The browser does not support websocket.");
}
};
// Socket message
function onSocketMessage(message) {
console.log('Message: ' + message.data);
};
// Socket error
function onSocketError(error) {
console.log('Error: ' + error.data);
};
// Socket connected
function onSocketConnected() {
console.log("Connected to socket server");
};
// Socket disconnected
function onSocketDisconnect() {
console.log("Disconnected from socket server");
};
I think, it is because you are using the Socket Package on the Java Server Side and the WebSocket API on the Client Side. Your idea is really good but the wrong technology.
Keep the WebSocket on the Client Side (Javascript) becaue you don't have lots of other possibilities, but try JWebSocket on the Server side (Java). In Fact WebSocket is using TCP/IP but its own communication protocol over TCP/IP. The Java Socket Package is purely TCP/IP. Re-write your server with JWebSocket, all details about JWebSocket can be found at:
http://jwebsocket.org/.
I hope my answer will help you.
you must specify end of return packet with "\r\n\r\n"
ret = "HTTP/1.1 101 Switching Protocols\r\n";
ret+="Upgrade: websocket\r\n";
ret+="Connection: Upgrade\r\n";
ret+="Sec-WebSocket-Accept: "+returnBase + "\r\n\r\n";
and for create accept key i use
public class WSKeyGenerator {
private final static String MAGIC_KEY =
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
public static String getKey(String strWebSocketKey) throws
NoSuchAlgorithmException {
strWebSocketKey += MAGIC_KEY;
MessageDigest shaMD = MessageDigest.getInstance("SHA-1");
shaMD.reset();
shaMD.update(strWebSocketKey.getBytes());
byte messageDigest[] = shaMD.digest();
BASE64Encoder b64 = new BASE64Encoder();
return b64.encode(messageDigest);
}
}
I recommend that use the http://websocket.org/echo.html to check the server's websocket functionality

Fastest way to scan ports with Java

I made a very simple port scanner, but it runs too slow, so I'm looking for a way to make it scan faster. Here is my code:
public boolean portIsOpen(String ip, int port, int timeout) {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ip, port), timeout);
socket.close();
return true;
} catch (Exception ex) {
return false;
}
}
This code tests if a specific port is open on a specific ip. For timeout I used a minimum value of 200 because when I go lower it doesn't have enough time to test the port.
It works well, but takes too much to scan from 0 to 65535. Is there any other way that could maybe scan from 0 to 65535 in less than 5 minutes?
If you need 200ms for each of the 65536 ports (in the worst case, a firewall is blocking everything, thus making you hit your timeout for every single port), the maths is pretty simple: you need 13k seconds, or about 3 hours and a half.
You have 2 (non-exclusive) options to make it faster:
reduce your timeout
paralellize your code
Since the operation is I/O bound (in contrast to CPU bound -- that is, you spend time waiting for I/O, and not for some huge calculation to complete), you can use many, many threads. Try starting with 20. They would divide the 3 hours and a half among them, so the maximum expected time is about 10 minutes. Just remember that this will put pressure on the other side, ie, the scanned host will see huge network activity with "unreasonable" or "strange" patterns, making the scan extremely easy to detect.
The easiest way (ie, with minimal changes) is to use the ExecutorService and Future APIs:
public static Future<Boolean> portIsOpen(final ExecutorService es, final String ip, final int port, final int timeout) {
return es.submit(new Callable<Boolean>() {
#Override public Boolean call() {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ip, port), timeout);
socket.close();
return true;
} catch (Exception ex) {
return false;
}
}
});
}
Then, you can do something like:
public static void main(final String... args) {
final ExecutorService es = Executors.newFixedThreadPool(20);
final String ip = "127.0.0.1";
final int timeout = 200;
final List<Future<Boolean>> futures = new ArrayList<>();
for (int port = 1; port <= 65535; port++) {
futures.add(portIsOpen(es, ip, port, timeout));
}
es.shutdown();
int openPorts = 0;
for (final Future<Boolean> f : futures) {
if (f.get()) {
openPorts++;
}
}
System.out.println("There are " + openPorts + " open ports on host " + ip + " (probed with a timeout of " + timeout + "ms)");
}
If you need to know which ports are open (and not just how many, as in the above example), you'd need to change the return type of the function to Future<SomethingElse>, where SomethingElse would hold the port and the result of the scan, something like:
public final class ScanResult {
private final int port;
private final boolean isOpen;
// constructor
// getters
}
Then, change Boolean to ScanResult in the first snippet, and return new ScanResult(port, true) or new ScanResult(port, false) instead of just true or false
EDIT: Actually, I just noticed: in this particular case, you don't need the ScanResult class to hold result + port, and still know which port is open. Since you add the futures to a List, which is ordered, and, later on, you process them in the same order you added them, you could have a counter that you'd increment on each iteration to know which port you are dealing with. But, hey, this is just to be complete and precise. Don't ever try doing that, it is horrible, I'm mostly ashamed that I thought about this... Using the ScanResult object is much cleaner, the code is way easier to read and maintain, and allows you to, later, for example, use a CompletionService to improve the scanner.
Apart from parallelizing the scan, you can use more advanced port scanning techniques like the ones (TCP SYN and TCP FIN scanning) explained here: http://nmap.org/nmap_doc.html. VB code of an implementation can be found here: http://h.ackack.net/spoon-worlds-fastest-port-scanner.html
In order to use these techniques, however, you need to use raw TCP/IP sockets. You should use RockSaw library for this.
Code sample is inspired by "Bruno Reis"
class PortScanner {
public static void main(final String... args) throws InterruptedException, ExecutionException {
final ExecutorService es = Executors.newFixedThreadPool(20);
final String ip = "127.0.0.1";
final int timeout = 200;
final List<Future<ScanResult>> futures = new ArrayList<>();
for (int port = 1; port <= 65535; port++) {
// for (int port = 1; port <= 80; port++) {
futures.add(portIsOpen(es, ip, port, timeout));
}
es.awaitTermination(200L, TimeUnit.MILLISECONDS);
int openPorts = 0;
for (final Future<ScanResult> f : futures) {
if (f.get().isOpen()) {
openPorts++;
System.out.println(f.get().getPort());
}
}
System.out.println("There are " + openPorts + " open ports on host " + ip + " (probed with a timeout of "
+ timeout + "ms)");
}
public static Future<ScanResult> portIsOpen(final ExecutorService es, final String ip, final int port,
final int timeout) {
return es.submit(new Callable<ScanResult>() {
#Override
public ScanResult call() {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ip, port), timeout);
socket.close();
return new ScanResult(port, true);
} catch (Exception ex) {
return new ScanResult(port, false);
}
}
});
}
public static class ScanResult {
private int port;
private boolean isOpen;
public ScanResult(int port, boolean isOpen) {
super();
this.port = port;
this.isOpen = isOpen;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public boolean isOpen() {
return isOpen;
}
public void setOpen(boolean isOpen) {
this.isOpen = isOpen;
}
}
}
I wrote my own asynchronous portscanner java service that can scan ports via TCP-SYN-Scan like Nmap does. It also support IMCP ping scans and can work with a very high throughput (depending on what the network can sustain):
https://github.com/subes/invesdwin-webproxy
Internally it uses a java binding pcap and exposes its services via JMS/AMQP. Though you can also use it directly in your application if you don't mind it having root permissions.
If you decide to use the Nmap option and want to continue with Java, you should look at Nmap4j on SourceForge.net.
It's a simple API that allows you to integrate Nmap into a java app.
Nay, fastest way here is to use the dynamically created thread method
Executors.newCachedThreadPool();
This way it uses threads until all of them are taken, then when all of them are taken and there is a new task it will open up a new thread and preform the new task on it.
Here's my code snippet (Creds due to Jack and Bruno Reis)
I also added the function to search any IP address you type in for some added functionality and ease of use.
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
class PortScanner {
public static void main(final String... args) throws InterruptedException, ExecutionException
{
final ExecutorService es = Executors.newCachedThreadPool();
System.out.print("Please input the ip address you would like to scan for open ports: ");
Scanner inputScanner = new Scanner(System.in);
final String ip = inputScanner.nextLine();
final int timeout = 200;
final List<Future<ScanResult>> futures = new ArrayList<>();
for (int port = 1; port <= 65535; port++) {
// for (int port = 1; port <= 80; port++) {
futures.add(portIsOpen(es, ip, port, timeout));
}
es.awaitTermination(200L, TimeUnit.MILLISECONDS);
int openPorts = 0;
for (final Future<ScanResult> f : futures) {
if (f.get().isOpen()) {
openPorts++;
System.out.println(f.get().getPort());
}
}
System.out.println("There are " + openPorts + " open ports on host " + ip + " (probed with a timeout of "
+ timeout + "ms)");
es.shutdown();
}
public static Future<ScanResult> portIsOpen(final ExecutorService es, final String ip, final int port,
final int timeout)
{
return es.submit(new Callable<ScanResult>() {
#Override
public ScanResult call() {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ip, port), timeout);
socket.close();
return new ScanResult(port, true);
} catch (Exception ex) {
return new ScanResult(port, false);
}
}
});
}
public static class ScanResult {
private int port;
private boolean isOpen;
public ScanResult(int port, boolean isOpen) {
super();
this.port = port;
this.isOpen = isOpen;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public boolean isOpen() {
return isOpen;
}
public void setOpen(boolean isOpen) {
this.isOpen = isOpen;
}
}
}
I may be late to this but you can do a bulk port scan by doing the following using NIO2 single-threaded. By following NIO2 code with a single thread, I am able to scan all the hosts for a given port. Please try a reasonable timeout and make sure you have large File Discriptor for process
public static List<HostTarget> getRechabilityStatus(String...hosts,final int port, final int bulkDevicesPingTimeoutinMS) throws Exception {
List<AsynchronousSocketChannel> channels = new ArrayList<>(hosts.length);
try {
List<CompletableFuture<HostTarget>> all = new ArrayList<>(hosts.length);
List<HostTarget> allHosts = new ArrayList(hosts.length);
for (String host : hosts) {
InetSocketAddress address = new InetSocketAddress(host, port);
HostTarget target = new HostTarget();
target.setIpAddress(host);
allHosts.add(target);
AsynchronousSocketChannel client = AsynchronousSocketChannel.open();
channels.add(client);
final CompletableFuture<HostTarget> targetFuture = new CompletableFuture<>();
all.add(targetFuture);
client.connect(address, target, new CompletionHandler<Void, HostTarget>() {
#Override
public void completed(Void result, HostTarget attachment) {
attachment.setIsReachable(true);
targetFuture.complete(attachment);
}
#Override
public void failed(Throwable exc, HostTarget attachment) {
attachment.setIsReachable(false);
attachment.errrorMessage = exc.getMessage();
targetFuture.complete(attachment);
}
});
}
try {
if(bulkDevicesPingTimeoutinMS > 0) {
CompletableFuture.allOf(all.toArray(new CompletableFuture[]{})).get(bulkDevicesPingTimeoutinMS, TimeUnit.MILLISECONDS);
}else{
// wait for all future to be complete 1000 scan is taking 7 seconds.
CompletableFuture.allOf(all.toArray(new CompletableFuture[]{})).join();
}
} catch (Exception timeoutException) {
// ignore
}
return allHosts;
}finally {
for(AsynchronousSocketChannel channel : channels){
try{
channel.close();
}catch (Exception e){
if(LOGGER.isDebugEnabled()) {
LOGGER.error("Erorr while closing socket",e);
}
}
}
}
static class HostTarget {
String ipAddress;
Boolean isReachable;
public String getIpAddress() {
return ipAddress;
}
public Boolean getIsReachable() {
return isReachable;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public void setIsReachable(Boolean isReachable) {
this.isReachable = isReachable;
}
}
Inspired by you all, but just this Code realy worked!
class PortScaner
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class PortScaner {
public static void main(String[] args) throws InterruptedException, ExecutionException {
final ExecutorService es = Executors.newFixedThreadPool(20);
final String ip = "127.0.0.1";
final int timeout = 200;
final List<Future<ScanResult>> futures = new ArrayList<>();
for (int port = 1; port <= 65535; port++)
futures.add(portIsOpen(es, ip, port, timeout));
es.shutdown();
int openPorts = 0;
for (final Future<ScanResult> f : futures)
if (f.get().isOpen()) {
openPorts++;
System.out.println(f.get());
}
System.out.println("There are " + openPorts + " open ports on host " + ip + " (probed with a timeout of " + timeout + "ms)");
}
public static Future<ScanResult> portIsOpen(final ExecutorService es, final String ip, final int port, final int timeout) {
return es.submit(
new Callable<ScanResult>() {
#Override
public ScanResult call() {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ip, port), timeout);
socket.close();
return new ScanResult(port, true);
} catch (Exception ex) {
return new ScanResult(port, false);
}
}
});
}
}
class ScanResult
public final class ScanResult {
private final int port;
private final boolean isOpen;
public ScanResult(int port, boolean isOpen) {
super();
this.port = port;
this.isOpen = isOpen;
}
/**
* #return the port
*/
public int getPort() {
return port;
}
/**
* #return the isOpen
*/
public boolean isOpen() {
return isOpen;
}
#Override
public String toString() {
return "ScanResult [port=" + port + ", isOpen=" + isOpen + "]";
}
}

Categories