How to make a SSL tcp server with java? - java

i'm trying to find out how to create a TCP server with SSL in java. But i don't get what i really need. Do i have to import key-files into java, and i so, how to do this? Or do i just need to change the type of the socket from Socket to SSLSocket? I've read some articles but couldn't find anything helpful because all of them just take http for communicating. I would need it for my own protocol. In my case it would be to have a program like this:
int port = 4444;
ServerSocket serverSocket = new ServerSocket(port);
System.err.println("Started server on port " + port);
// repeatedly wait for connections, and process
while (true) {
// a "blocking" call which waits until a connection is requested
Socket clientSocket = serverSocket.accept();
System.err.println("Accepted connection from client");
// open up IO streams
In in = new In (clientSocket);
Out out = new Out(clientSocket);
// waits for data and reads it in until connection dies
// readLine() blocks until the server receives a new line from client
String s;
while ((s = in.readLine()) != null) {
out.println(s);
}
// close IO streams, then socket
System.err.println("Closing connection with client");
out.close();
in.close();
clientSocket.close();
}
to use a SSL connection. So how to do this?
Thanks,
Thomas

I found this with a quick Google search.
Here.

Related

Make Java IO Socket listen just like a ServerSocket

I'm doing a financial messaging integration as follows:
A server has an interface listening for requests from a client socket on a specific IP and port
Server sends a response for every request, back to the client socket
Also, server sends requests to the same client socket
The following is working perfectly:
The client socket (Socket object of Java IO) successfully sends requests to the server interface
The client socket successfully receives response for every request
try {
Socket clientSocket = new Socket("example.com", 8888);
BufferedWriter output = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
output.write(data);
output.flush();
BufferedReader input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// Read responses or new request from input
} catch (IOException e) {
e.printStackTrace();
}
The client socket is supposed to receive any request from the server - the same way it's receiving responses from the same sever. However, when a server initiates a request to the client socket, the request is never received. However, we can trace the traffic from the tcpdump on the client environment.
How can I make the client socket listen to requests from the server, and not just responses?
Update
It might help to clarify something on this integration:
a. The 'server' in this case is a third party system, with it's integration rules
b. My client socket posts message to the server (above)
c. My implementation listens to responses and requests from the third party system server, either by creating my own server socket (ruled out), or using the very client socket I'm sending with (the solution I was seeking)
This is a very common mistake, you are writing a message without writing "\n" (end line identifier) at the end so no messages will be read. To fix this use PrintWriter with println.
That will send a line to the other socket.
Here is an example of a thread-per-client model of a server
//create a new server socket with the port as a parameter, this will bind it to the specified port: 6000
ServerSocket server = new ServerSocket(6000);
System.out.println("Binded");
//create a while loop accepting sockets
while(true)
{
//accept a socket
Socket client = server.accept();
System.out.println("Client has connected");
//create a new thread for this socket
new Thread(() ->
{
try
{
/*
create a print writer so you can write a line, not only a message like BufferedWriter does,
if for some reason you still want to use BufferedWriter use
writer.write(message + "\n");
*/
PrintWriter writer = new PrintWriter(new OutputStreamWriter(client.getOutputStream()));
//Create a new reader
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
System.out.println("Waiting for requests...");
//create a while loop reading requests (lines)
String request;
while((request = reader.readLine()) != null)
{
System.out.println("Received message: " + request);
//here find the correct response and return it, I just sent a message, replace it with the correct response
writer.println("Hello there! How are you today?");
//flush, flushing will write the data to the client
writer.flush();
}
} catch(IOException e)
{
//print an exception if it occurred, if an exception occurrs its most likely just a disconnection exception
e.printStackTrace();
}
}).start();
}
and here is an example of a client
//connect to the server at "localhost" on port 6000
Socket client = new Socket("localhost", 6000);
System.out.println("Connected");
/*
create a print writer so you can write a line, not only a message like BufferedWriter does,
if for some reason you still want to use BufferedWriter use
writer.write(message + "\n");
*/
PrintWriter writer = new PrintWriter(new OutputStreamWriter(client.getOutputStream()));
//Create a new reader
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
//write a request
writer.println("Hi there!");
//flush, flushing will write the data to the server
writer.flush();
System.out.println("Written");
System.out.println("Waiting for responses...");
//create a while loop reading responses (lines)
//you may want to do this while loop in another thread
String response;
while((response = reader.readLine()) != null)
{
System.out.println("Received response: " + response);
}
Also if this is involved with financial information I recommend using TLS (SSL).
You don't have to worry Java already has it implemented and has made it easy to use, here is an example of a server
//create a new SSL server socket with the port as a parameter, this will bind it to the specified port: 6000
//you create it by getting the default SSLServerSocketFactory which will create a new SSLServerSocket
//you need to cast it since it actually returns ServerSocket but SSLServerSocket extends ServerSocket and this returns SSLServerSocket so it is safe
SSLServerSocket server = (SSLServerSocket) SSLServerSocketFactory.getDefault().createServerSocket(6000);
System.out.println("Binded");
//set the enabled ciphersuites, until you buy a certificate set only to ciphersuites with "anon" more info on ciphersuites on https://en.wikipedia.org/wiki/Cipher_suite
server.setEnabledCipherSuites(new String[]{"TLS_ECDH_anon_WITH_AES_256_CBC_SHA"});
//create a while loop accepting sockets
while(true)
{
//accept a socket a SSLSocket
SSLSocket client = (SSLSocket) server.accept();
System.out.println("Client has connected");
//create a new thread for this socket
new Thread(() ->
{
try
{
//begin a handshake more info about handshakes in https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.1.0/com.ibm.mq.doc/sy10660_.htm
client.startHandshake();
/*
create a print writer so you can write a line, not only a message like BufferedWriter does,
if for some reason you still want to use BufferedWriter use
writer.write(message + "\n");
*/
PrintWriter writer = new PrintWriter(new OutputStreamWriter(client.getOutputStream()));
//Create a new reader
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
System.out.println("Waiting for requests...");
//create a while loop reading requests (lines)
String request;
while((request = reader.readLine()) != null)
{
System.out.println("Received message: " + request);
//here find the correct response and return it, I just sent a message, replace it with the correct response
writer.println("Hello there! How are you today?");
//flush, flushing will write the data to the client
writer.flush();
}
} catch(IOException e)
{
//print an exception if it occurred, if an exception occurrs its most likely just a disconnection exception
e.printStackTrace();
}
}).start();
}
And here is an example of a client
//connect to the server at "localhost" on port 6000
//you create a SSLSocket by getting the default SSLSocketFactory which will create a new SSLSocket
//you need to cast it since it actually returns Socket but SSLSocket extends Socket and this returns SSLSocket so it is safe
SSLSocket client = (SSLSocket) SSLSocketFactory.getDefault().createSocket("localhost", 6000);
System.out.println("Connected");
//set the enabled ciphersuites to everything supported so the server can decide the ciphersuite, you can modify this to specified ciphersuites
client.setEnabledCipherSuites(client.getSupportedCipherSuites());
//begin a handshake more info about handshakes in https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.1.0/com.ibm.mq.doc/sy10660_.htm
client.startHandshake();
/*
create a print writer so you can write a line, not only a message like BufferedWriter does,
if for some reason you still want to use BufferedWriter use
writer.write(message + "\n");
*/
PrintWriter writer = new PrintWriter(new OutputStreamWriter(client.getOutputStream()));
//Create a new reader
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
//write a request
writer.println("Hi there!");
//flush, flushing will write the data to the server
writer.flush();
System.out.println("Written");
System.out.println("Waiting for responses...");
//create a while loop reading responses (lines)
//you may want to do this while loop in another thread
String response;
while((response = reader.readLine()) != null)
{
System.out.println("Received response: " + response);
}

How to keep Socket Connection until Server Process it?

I am writing Socket program , Here Client Sends a String through Stream , Server Process it and writes back to Client. My problem is, after Server process the String , it Writes back to Stream but in client It can't able to read the Stream its showing exception as Exception in while: java.net.SocketException: socket closed Here is my code,
Client ,
public void run() {
while (true) {
try {
// Open your connection to a server, at port 1231
s1 = new Socket("localhost", 1231);
OutputStream s1out = s1.getOutputStream();
DataOutputStream dos = new DataOutputStream(s1out);
InputStream in=s1.getInputStream();
DataInputStream dis=new DataInputStream(in);
String s = br.readLine();
dos.writeUTF(s);
dos.flush();
dos.close();
System.out.println(dis.readUTF());//it is the String from Server after processing
dis.close();
} catch (IOException ex) {
// Logger.getLogger(SimpleClient.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("Exception in while: " + ex);
}
}
In Server
public void run()
{
while(true){
try {
System.out.println("Waiting for connect to client");
s1=serverSocket.accept();
s1In = s1.getInputStream();
dis = new DataInputStream(s1In);
out=s1.getOutputStream();
dos=new DataOutputStream(out);
String clientData=dis.readUTF();
//processing task String
dos.writeUTF("Bus Registered Successfully");
dos.flush();
}
}
Here I am not able to read Bus Registered Successfully at client side . How to Solve this.?
Well there are many things not right in your program. But first let me answer your question ... you are closing the socket just after writing the stream ... so server throws exception, just remove dos.close(); just after the dos.flush();. It will run fine.
Now back to the programming practices ...
1) Server should accept the connection in a while(true) loop and then make a new thread. So following statement should not be the part of run method.
System.out.println("Waiting for connect to client");
s1=serverSocket.accept();
s1In = s1.getInputStream();
dis = new DataInputStream(s1In);
out=s1.getOutputStream();
dos=new DataOutputStream(out);
2) There is no need of run method in client. Because Every new client will be a new program that has its own variables and socket.
A quick look shows me that the reason the socket is closed is because you used dos.close().
Closing a DataInputStream (or PrintStream, or any similiar stream) will close the underlying socket.
Just take out dos.close().
You can also move the dos.close() to the very end of the try block. As a general rule, don't close anything related to the socket until you're done with the socket.

Android TCP ServerSocket.accept() blocking

I've been working on a simple Android TCP Server, so I can connect from a TCP Client and pass data back and forth.
I am encountering an weird problem, my android phone creates the TCP Socket, and I am able to connect to it via Hercules utility (A TCP client). The connection goes through, however the program is still blocking at the ServerSocket.accept() method.
Could anyone shed some light on this issue? Here is my java function.
public void TcpServer()
{
try
{
Socket s = null;
ServerSocket ss = null;
System.out.println("TCP Server Starting");
ss = new ServerSocket(27015);
s = ss.accept();
System.out.println("New connection! Yay");
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
String incomingMsg = input.readLine();
System.out.println("Received: " + incomingMsg);
}
catch (Exception e)
{
}
}

What is the benefit of creating an unconnected socket in Java?

In the code I'm studying, I see this line:
Socket clientSocket = new Socket();
So this is just a raw socket, connecting to nowhere? Why would you use this kind of socket that is not bound to a port?
I see on the API that it is "with the system-default type of SocketImpl."
You do this when you want to connect with a timeout:
Socket s = new Socket();
try
{
s.connect(address, timeout);
}
catch (SocketTimeoutExceptione exc)
{
// connect timeout
}

Checking for a client disconnect on a Java TCP server - output only

I have a Java TCP server which, when a client connects to it, outputs a message to the client every 30 seconds. It is a strict requirement that the client does not send any messages to the server, and that the server does not send any data other than the 30-second interval messages to the client.
When I disconnect the client, the server will not realise this until the next time it tries to write to the client. So it can take up to 30 seconds for the server to recognise the disconnect.
What I want to do is check for the disconnect every few seconds without having to wait, but I am not sure how to do this given that a) the server does not receive from the client and b) the server cannot send any other data. Would anyone please be able to shed some light on this? Thanks.
Even though your server doesn't "receive" from the client, a non-blocking read on the client socket will tell you that either there's nothing to be read (as you expect), or that the client has disconnected.
If you're using NIO you can simply use a non-blocking Selector loop (with non-blocking sockets) and only write on your 30 second marks. If a SelectionKey is readable and the read on the SocketChannel returns -1 you know the client has disconnected.
EDIT: Another approach with blocking is simply to select with a 30 second timeout. Any client disconnects will cause the select to return and you'll know which ones those are via the read set. The additional thing you'd need to do there is track how long you were blocked in the select to figure out when to do your writes on the 30 second mark (Setting the timeout for the next select to the delta).
Big Edit: After talking to Myn below, offering complete example:
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(1);
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
// Set a 1 second timeout on the socket
clientSocket.setSoTimeout(1000);
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
long myNextOutputTime = System.currentTimeMillis() + 30000;
String inputLine = null;
boolean connected = true;
while (connected)
{
try {
inputLine = in.readLine();
if (inputLine == null)
{
System.out.println("Client Disconnected!");
connected = false;
}
}
catch(java.net.SocketTimeoutException e)
{
System.out.println("Timed out trying to read from socket");
}
if (connected && (System.currentTimeMillis() - myNextOutputTime > 0))
{
out.println("My Message to the client");
myNextOutputTime += 30000;
}
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
}
Worth noting here is that the PrintWriter really moves you far away from the actual socket, and you're not going to catch the socket disconnect on the write (It will never throw an exception, you have to manually check it with checkError()) You could change to using a BufferedWriter instead (requires using flush() to push the output) and handling it like the BufferedReader to catch a disco on the write.
If you are managing multiple clients then I guess you would be using Non-Blocking sockets (If not then consider using Non-Blocking). You can use Selector to monitor all the connected sockets to check if they are readable or writeable or there is some Error on that socket. When some client disconnects, your Selector will mark that socket and will return.
For more help google "Socket Select function"

Categories

Resources