I am using TCP/IP sockets to create a client and server applicaton. Originally I was using regular sockets but now I have decided to use SSL for my connection. I have created a keystore and have tried running my application but it has yet to be successful.
Here is my code for the server
public class ArFileServer {
public static void main(String[] args)
{
boolean listening = true;
ServerSocketFactory serversocketfactory;
ServerSocket serverSocket;
try
{
//serverSocket = new ServerSocket(4445);
serversocketfactory = SSLServerSocketFactory.getDefault();
serverSocket = serversocketfactory.createServerSocket(4445);
String keystore = System.getProperty("javax.net.ssl.trustStore");
System.out.println(keystore);
// infinite loop to continually listen for connection requests made by clients
while (listening)
{
new ClientConnection(serverSocket.accept()).start();
if (serverSocket != null)
{
System.out.println("Connection to client established");
}
}
serverSocket.close();
}
catch (IOException e)
{
System.out.println("Error could not create socket connection to port, check that port is not busy");
}
}
}
and here is the client code:
public class ClientSocket
{
SocketFactory socketfactory = null;
Socket clientSocket = null;
PrintWriter out = null;
BufferedReader in = null;
// establish a connection to All Care's server application through socket 4444 (adjust localhost to reflect the IP address that the server
// is being run from)
public ClientSocket()
{
try
{
//clientSocket = new Socket("localhost", 4445);
//SocketFactory socketfactory = SSLSocketFactory.getDefault();
clientSocket = socketfactory.createSocket("192.168.1.8", 4445);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String truststore = System.getProperty("javax.net.ssl.trustStore");
System.out.println(truststore);
}
catch (IOException e)
{
System.out.println("Could not connect to All Care Server Application : " + e.getMessage());
}
}
}
I am also using these runtime arguments:
-Djavax.net.ssl.keyStore=C:\Users\Chris\Documents\NetBeansProjects\ArFile\keystore.jks -Djavax.net.ssl.keyStorePassword=password
When I try to print out the truststore it always returns null, what am I doing wrong?
When I try to print out the truststore it always returns null
Because you never set it. All you are doing is printing out the value of a system property. If you didn't set it, it is null.
what am I doing wrong?
Nothing yet, except printing out meaningless information. But much of your code doesn't make sense:
if (serverSocket != null)
{
System.out.println("Connection to client established");
}
serverSocket being non-null (a) is inevitable at this point, and (b) doesn't have anything do with the client socket being established, which is inevitable at this point.
catch (IOException e)
{
System.out.println("Error could not create socket connection to port, check that port is not busy");
}
An IOException at this point could mean many things, but the one thing it doesn't mean is 'cannot create socket connection to port'. It is the client that does the connecting: the server accepts connections. When you catch an exception, always print its message, don't just make up your own.
You need to define both trustStore and keyStore in runtime arguments:
-Djavax.net.ssl.keyStore=xxx.ks
-Djavax.net.ssl.keyStorePassword=yyy
-Djavax.net.ssl.trustStore=xxx.ks
-Djavax.net.ssl.trustStorePassword=yyy
Both can be same file.
trustStore contains public keys of others.
keyStore contains own keys and certificates.
Related
How to use socket to setup a SMTP server? I don't want to use any library like WISER. I just want a very simple SMTP server. How to setup?
I have tried to use the following code. But it seems like wrong.
try {
// TODO code application logic here
InetSocketAddress isa = new InetSocketAddress(25);
ServerSocket server = new ServerSocket();
server.bind(isa);
System.out.println("Server starting...");
while (true) {
System.out.println("Waiting...");
Socket client = server.accept();
if (client != null) {
System.out.println("connected");
}
}
} catch (IOException ex) {
Logger.getLogger(Fakeserver.class.getName()).log(Level.SEVERE, null, ex);
}
If I make a socket connection from an application that is running on an application server, where does the returned data go? Is it necessary to create a receiving server socket in the application with a specified port, or is it received on the port at which the server is using to connect to the application and I just need to write something that will extract that data?
Here is the code to read from a socket. You are making socket connection to port 8080 in server. You don't have to worry about the OS -> Server port.
public static void readSocket() throws IOException {
try (Socket s = new Socket(InetAddress.getByName(new URL("Some Address").getHost()), 8080);
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()))) {
String line = null;
while ((line = input.readLine()) != null) {
System.out.println(line);
}
}
}
The socket is one end-point of two-way communication link between server and client programs of the network.
The returned data is sending to your client Socket object, lets call it clientSocket. You need to call clientSocket.getInputStream() to decode it.
No, you dont need to create a receiving server socket in the application. Your client program establishes a connection to the server on your given host and port. clientSocket can both send data to server and receive data from server.
For example the client side code:
private PrintWriter out = null;
private BufferedReader in = null;
public void listenSocket(){
//Create socket connection
try{
clientSocket = new Socket(HOST, PORT);
// use out object to send data to server applicaiton
out = new PrintWriter(clientSocket.getOutputStream(),
true);
// uses in object to receive data from server application
in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
} catch (UnknownHostException e) {
System.out.println("Unknown host:" + HOST);
System.exit(1);
} catch (IOException e) {
System.out.println("No I/O");
System.exit(1);
}
}
I want to check the online/offline status about a Database Server with Java.
Can I check this with a Socket connection over the port? I want to do this wihtout a Database connection with jdbc because the login and Database system info is unknown.
You can try the following:
try {
Socket socket = new Socket("127.0.0.1", port); //Port dependent on your DB/Server
// Server is up
socket.close();
}
catch (IOException e)
{
// Server is down
}
Yes, you can just open a Socket to the address and port of your databse server, if you get an IOException the server is down. (tested with postgress)
public boolean isDatabaseOnline(String address, int port) {
boolean result;
try {
Socket socket = new Socket(address, port);
socket.close();
result = true;
} catch (IOException e) {
result = false;
}
return result;
}
The above approaches don't really consider timing out in case the remote is unreachable, and a reasonable timeout should be defined because the default value is 20 seconds!!
You can state a timeout using the socket.connect method AFTER you create a blank socket.
SocketFactory sf = SocketFactory.getDefault();
try (Socket socket = sf.createSocket()) {
socket.connect(new InetSocketAddress(ipAdder, port), timeoutInMillis);
logger.info("database is up");
} catch (IOException e) {
logger.info("database is down");
}
The example above uses try with resources
I have a SSLServerSocket in Java, when a client is connected, I create a thread for its communication:
System.setProperty("javax.net.ssl.keyStore", "keystore");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
SSLServerSocket server = (SSLServerSocket)null;
if(ipSocket == null){
ipSocket = new HashMap<String,java.net.Socket>();
}
try {
SSLServerSocketFactory sslserversocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
server = (SSLServerSocket) sslserversocketfactory.createServerSocket(4380);
log.info("Server started");
} catch(IOException e) {
e.printStackTrace();
}
while(true){
try {
SSLSocket client = (SSLSocket) server.accept();
log.info("new client");
} catch (Exception e){
e.printStackTrace();
}
}
The problem is when the code sometimes rejects connections. It happens when the code is running for a while, so I think the problem is the clients lost the connection and reconect, but the previous thread is still alive, and there is a maximun SSLServerSockets.
Could this happen? What number is the maximum?
How can I kill the threads when a disconnection happens?
Based on your code and my understanding of networking (both from the lower level and from the API level) you may be incorrectly using the API.
At a high level, you want to do this a little differently
public static void main(String[] args) {
System.setProperty("javax.net.ssl.keyStore", "keystore");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
SSLServerSocket server = (SSLServerSocket)null;
if(ipSocket == null){
ipSocket = new HashMap<String,java.net.Socket>();
}
try {
SSLServerSocketFactory sslserversocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
// Creates a socket with a default backlog of 50 - meaning
// There will be a maximum of 50 client connection attempts on this
// socket after-which connections will be refused. If the server is
// overwhelmed by more than that number of requests before they can be
// accepted, they will be refused
// The API allows for you to speccify a backlog.
server = (SSLServerSocket) sslserversocketfactory.createServerSocket(4380);
log.info("Server started");
} catch(IOException e) {
e.printStackTrace();
}
while(true){
try {
// This will take one of the waiting connections
SSLSocket client = (SSLSocket) server.accept();
log.info("new client");
// HERE is where you should create a thread to execute the
// conversation with the client.
} catch (Exception e){
e.printStackTrace();
}
}
}
I hope that more correctly answers your question.
In regards to the comment by EJP - I have updated my explanation and cited the documentation located here:
The maximum queue length for incoming connection indications (a request to connect) is set to the backlog parameter. If a connection indication arrives when the queue is full, the connection is refused.
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.
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
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).