user2430608
user2430608

Reputation:

Java multiple SSL client to one server

I'm currently working on a tiny individual project for this semester with Android. What I'm going to do is making lots of connections to my https server with my Android phone so the server goes down. I know absolutely nothing about programming because I'm studying networking not computer language. But I somehow collected from here and there piece by piece and made a code like below. I think it's using a socket connection.

import java.net.*;
import java.io.*;
import java.security.*;
import javax.net.ssl.*;

public class HTTPSClient {
    public static void main(String[] args) {
        System.out.println("Usage: java HTTPSClient host");

        int port = 443; // default https port
        String host = "192.168.0.8";

        TrustManager[] trustAll = new javax.net.ssl.TrustManager[]{
          new javax.net.ssl.X509TrustManager(){
              public java.security.cert.X509Certificate[] getAcceptedIssuers(){
                return null;
              }
              public void checkClientTrusted(java.security.cert.X509Certificate[] certs,String authType){}
              public void checkServerTrusted(java.security.cert.X509Certificate[] certs,String authType){}
          }
        };

        try {
            javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
            sc.init(null, trustAll, new java.security.SecureRandom());

            Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
            SSLSocketFactory factory = (SSLSocketFactory) sc.getSocketFactory();
            SSLSocket socket = (SSLSocket) factory.createSocket(host, port);

            Writer out = new OutputStreamWriter(socket.getOutputStream());
            out.write("GET / HTTP/1.0\\r\\n");
            out.write("\\r\\n");
            out.flush();

            // read response
            BufferedReader in = new BufferedReader(
            new InputStreamReader(socket.getInputStream()));
            int c;
            while ((c = in.read()) != -1) {
                System.out.write(c);
            }
            // out.close();
            // in.close(); 
            // socket.close();

        } catch (Exception e) {
            System.err.println(e);
        }
    }
}

I enabled https on my macbook and I can see the port 443 listening. When I execute the code above I can see one established connection through 'netstat -an | grep 443' until I stop it. My question is this: if I want to make multiple connection with this code, what should I add on? Is it possible with this code? My idea is that if I can see heaps of established connections to 443 port on my macbook, I will not be able to connect https:://localhost with a browser because the machine is down. I don't know if it's correct but I hope. Because the semester is almost over and I anyway have to make something to report.

I'm not sure if that code will be the same when I make the code for Android phone but I just want to see something happening first. I'm really desperate, please help me. Thank you very much.

Upvotes: 2

Views: 2295

Answers (2)

guyfleeman
guyfleeman

Reputation: 473

From what I can understand, you are trying to have multiple clients(phones) connect to your server.

Your server looks solid. You should be able to modify it to handle multiple clients easily.

Generally you need a handler of some sort to process incoming client connections. You will need a loop to wait for new connections, and then a thread to handle each connection independently. Each instance of a socket can only handle one connection. A socket factory allows you to bind more than once instance of a socket to the server. I have two classes to handle multiple connections. My first class is the server itself and the second is a a thread to handle each client.

If you are not familiar with threading, you should check into it.

This is the server class:

public class ServerThread extends Thread
{
    private Vector<ClientHandlerThread> connectedClients = new Vector<ClientHandlerThread>(20, 5);

   public void run()
   {
    SSLServerSocket sslDataTraffic = null;
    SSLServerSocket sslFileTraffic = null;
    SSLServerSocketFactory sslFac = null;

    try
    {
        System.out.print("Validating SSL certificate... ");
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(new FileInputStream(certificateDir), password);
        System.out.println("DONE.");

        System.out.print("Creating trust engine........ ");
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(keyStore);
        System.out.println("DONE.");

        System.out.print("Creating key engine.......... ");
        KeyManagerFactory kmf = KeyManagerFactory.getInstance((KeyManagerFactory.getDefaultAlgorithm()));
        kmf.init(keyStore, password);
        System.out.println("DONE.");

        System.out.print("Creating SSL context......... ");
        System.setProperty("https.protocols", "SSL");
        SSLContext  ctx = SSLContext.getInstance("SSL");
        ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
        sslFac = ctx.getServerSocketFactory();
        System.out.println("DONE.");
    }
    catch (Exception e) {}

    try
    {
        System.out.print("Creating data socket......... ");
        sslDataTraffic = (SSLServerSocket) sslFac.createServerSocket(dataPort);
        System.out.println("DONE. Est. on:" + dataPort);
    }
    catch (IOException e)
    {
        System.out.println("FAILED.");
        System.out.println(e.toString() + " ::: " + e.getCause());
        System.exit(-1);
    }

    try
    {
        System.out.print("Creating file socket......... ");
        sslFileTraffic = (SSLServerSocket) sslFac.createServerSocket(filePort);
        System.out.println("DONE. Est. on:" + filePort);

    }
    catch (IOException e)
    {
        System.out.println("FAILED.");
        System.out.println(e.toString() + " ::: " + e.getCause());
        System.exit(-1);
    }

    while (running)
        {
            SSLSocket sslDataTrafficSocketInstance = (SSLSocket) sslDataTraffic.accept();
            SSLSocket sslFileTrafficSocketInstance = (SSLSocket) sslFileTraffic.accept();
            ClientHandlerThread c = new ClientHandlerThread(sslDataTrafficSocketInstance, sslFileTrafficSocketInstance);
            c.start();
            connectedClients.add(c);
        }
}

Notice the while loop at the end of the class. It will wait until a client connects (which invokes the accept() method). An independent thread is created to handle that client (phone).

The client thread is as follows:

public class ClientHandlerThread extends Thread
{
private boolean running = true;

private SSLSocket dataSocket;
private SSLSocket fileSocket;

private PrintWriter writer;
private BufferedReader reader;
private InputStream inputStream;
private OutputStream outputStream;

public ClientHandlerThread(
        SSLSocket dataSocket,
        SSLSocket fileSocket)
{
    this.dataSocket = dataSocket;
    this.fileSocket = fileSocket;

    try
    {
        this.reader = new BufferedReader(new InputStreamReader(this.dataSocket.getInputStream()));
        this.writer = new PrintWriter(this.dataSocket.getOutputStream());
        this.inputStream = fileSocket.getInputStream();
        this.outputStream = fileSocket.getOutputStream();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }

    this.ip = this.dataSocket.getInetAddress().getHostAddress();
}

public void run()
{
    try
    {
        writer.println("SERVER_HANDSHAKE_INIT");
        writer.flush();

        String fromClient;
        while (running && (fromClient = reader.readLine()) != null)
        {
            if (fromClient.equals("CLIENT_HANDSHAKE_INIT"))
                System.out.println("Client Connected: " + getIP());
        }
    }
    catch (IOException e)
    {
        e.getCause();

    }
}

    public String getIP()
{
    return ip;
}

public boolean isRunning()
{
    return running;
}

public void setRunning(boolean running)
{
    this.running = running;
}
}

You now have the ability to iterate through each client thread held within the Vector containing all clients. This will allow you to handle multiple clients and interact with each of them independently. This includes reading input/output streams.

These classes are stripped down versions of the ones I use for a simple remote management system I developed over the summer. You should be able to modify them as necessary to meet your needs. You could add a parameter to the client thread constructor to keep track of naming for example.

I hope this explained how to handle multiple incoming connections to a server. Feel free to DM or email me for additional info.

Cheers

Upvotes: 1

Scott Heaberlin
Scott Heaberlin

Reputation: 3424

You could change your code to open connections in a loop:

        int numConnections = 100;
        for (int i=0; i<numConnections; i++) {
            SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
            Writer out = new OutputStreamWriter(socket.getOutputStream());
            out.write("GET / HTTP/1.0\\r\\n");
            out.write("\\r\\n");
            out.flush();

            // read response
            BufferedReader in = new BufferedReader(
            new InputStreamReader(socket.getInputStream()));
            int c;
            while ((c = in.read()) != -1) {
                System.out.write(c);
            }
            // out.close();
            // in.close(); 
            // socket.close();
        }

I highly suggest retaining the socket objects in an array or collection variable and closing the I/O streams and socket when you are done, but this will also be done when main() exits - just know this is generally bad practice in programming if you were to want to reuse this code in a situation where the whole program didn't exit after the block of code that opens connection(s).

Upvotes: 0

Related Questions