SSL Socket connect timeout - java

How can I configure connect timeout for SSL Sockets in Java?
For plain sockets, I can simply create new socket instance without any target endpoint using new Socket(), and then call connect(SocketAddress endpoint, int timeout) method. With SSL sockets, I cannot create new SSLSocket() and SSLSocketFactory.getDefault().createSocket() method with no endpoint throws UnsupportedOperationException with Unconnected sockets not implemented message.
Is there a way to use connect timeouts for SSL Sockets in Java, using standard java libs only?

I believe you could use your current approach of creating the Socket and then connecting it. To establish SSL over the connection you could use SSLSocketFactory.createSocket
Returns a socket layered over an
existing socket connected to the named
host, at the given port.
This way you get full control over the connection and then you negociate setting up SSL on top of it. Please let me know if I misread your question.

With java 1.7 the following does not throw the exception stated in the question:
String host = "example.com";
int port = 12345;
int connectTimeout = 5000;
SSLSocket socket = (SSLSocket)SSLSocketFactory.getDefault().createSocket();
socket.connect(new InetSocketAddress(host, port), connectTimeout);
socket.startHandshake();
so it's business as usual.

Elaborating on #predi's answer, I found that I needed to use "setSoTimeout" too. Otherwise sometimes it gets stuck in the handshake (on very unstable connections):
final int connectTimeout = 30 * 1000;
SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
socket.setSoTimeout(connectTimeout);
socket.connect(new InetSocketAddress(hostAddress, port), connectTimeout);
socket.startHandshake();
socket.setSoTimeout(0);`

Related

Android: Get DatagramSocket from a SocketFactory in JAVA

Is there way to get DatagramSocket from SocketFactory in android?
https://developer.android.com/reference/javax/net/SocketFactory.html
createSocket
added in API level 1
Socket createSocket (String host,
int port)
Above get the Socket which is TCP kinds.. Need a DatagramSocket UDP socket.
Is this possible?
Use case:
https://developer.android.com/reference/android/net/Network.html#getSocketFactory()
From Network.getSocketFactory get a DatagramSocket specifically.
Thanks
Nithin
Starting with API level 22, you can use Network.bindSocket(DatagramSocket)
Binds the specified DatagramSocket to this Network. All data traffic on the socket will be sent on this Network, irrespective of any process-wide network binding set by bindProcessToNetwork(Network). The socket must not be connected.

Using same address and port for accepting and connecting in Java

(This might have been asked a thousand times, but I do not get it straight.)
Suppose I have the following snippet:
InetAddress localAddress = InetAddress.getByName("192.168.1.10");
int localPort = 65000;
InetAddress targetAddress = InetAddress.getByName("192.168.1.20");
int targetPort = 65000;
// Create a new serversocket
ServerSocket ss = new ServerSocket(localPort, 50, localAddress);
// Wait for an incoming connection...
Socket acceptedSocket = ss.accept();
// Do something with the accepted socket. Possibly in a new thread.
Set up new connection...
Socket socket = new Socket(targetAddress, targetPort, localAddress, localPort);
// Write something to the socket.
Now can I use the same address and port for both accepting an incoming connection and connecting to an address? If it can, then how? If not, then why not? According to this post, ports can be shared, so it shouldn't be a problem.
How does it work?
You can only establish a connection by having the connecting socket use the same address and port. (Ignoring the use of multi-homed servers)
A single connection is a unique combination of both the source address+port and destination address+port, so you can have the same destination if you have a different source.
In other words, can you write server program that that contains client connecting to itself? The answer is yes, surely. All integration tests do this running in-process server and connecting to it.

I am trying to create sockets with different URLs. How can i handle failed connections?

I have a database in which there are different hosts on which i want to connect to through SSL. Because the hosts sometimes are random and often invalid i get an error at the point where the socket is created. I don't know how i can handle this problem
for(int i=connect.getMinId();i<connect.getMaxId();i++){
System.out.println(connect.getHost(i));
SSLSocket socket = (SSLSocket) factory.createSocket(URL, 443);
socket.startHandshake();
SSLSession session = socket.getSession();
}
Create an unconnected Socket with new Socket().
Connect it with a timeout using Socket.connect(address, timeout). You can choose your own timeout up to the platform default. Note that the Javadoc incorrect says that 0 means an infinite timeout. It doesn't: it means the platform default, which is around a minute, dependent on the, err, platform. This method throws SocketTimeoutException if the timeout expires.
Wrap it in an SSLSocket with SSLSocketFactory.createSocket(Socket, host, port, true). Note that you have to re-specify the host and port: this is for SSL session sharing purposes; it doesn't create a new connection.
Get the session, or start the handshake. Note that getting the session starts the handshake, you don't have to do both. If you're not interested in the server certificate you don't really need to do this step at all.
Catch all IOExceptions and close the socket.

java server socket in cloud server

So I have two java classes for socket server and client as follows:
For the server:
System.out.println("Server started:");
ServerSocket server = new ServerSocket(1935, 0, InetAddress.getByName("localhost"));
Socket connection = new Socket();
while(active){
connection = server.accept();
printTimeStamp();
InputStream in = connection.getInputStream();
while(in.available() == 0){
//waiting till message is complete
}
MessageDecode(in);
}
MessageDecode is just an internal method that reads the input streams and stores it somewhere
for the client
Socket connectionSocket = new Socket();
InetAddress address = InetAddress.getByName("THE_CLOUD_SERVER_IP");
SocketAddress sAddress = new InetSocketAddress(address, 1935);
connectionSocket.setKeepAlive(true);
connectionSocket.setTcpNoDelay(true);
connectionSocket.connect(sAddress, 2000);
OutputStream os = connectionSocket.getOutputStream();
os.write("HELLO SERVER".getBytes());
os.close();
System.out.println("sent");
when I run both on a localhost it works like a charm, but when I run the class into the cloud server, I get timout exception java.net.SocketTimeoutException: connect timed out
even when the por is listening, I know its listening because when I run the app, and do a netstat -anp I get:
tcp 0 0 127.0.0.1:1935 0.0.0.0:* LISTEN PID/java
can someone give me a clue on how to solve this?
your help is must appreciated.
Thanks (._.')
As far as I know, cloud providers do not allow to open low level sockets (even WebSocket are rarely allowed). They usually use a proxy in front of the Java application server. Cloud providers are often used for HTTP application.
If you really want to use sockets, leave your current cloud provider and open an account on Amazon EC2.

How to implement (SSL/TLS) secure communication through normal Java Sockets

How can I secure ordinary socket communication? I wrote a Jabber client that can only connect to dedicated SSL ports(5223) (using SSLSocket). The normal way is to connect to Jabber standard port 5222 and request starttls. How can I achieve that?
I'm not completely sure what you are asking, but you can layer a secure socket on an existing normal (non-secure) socket by using the SSLSocketFactory.createSocket() method. This is one way to "upgrade" a socket using something like starttls. But this is doing things the hard way. Almost certainly your XMPP library will provide high-level access to this kind of functionality.
Expectation Management: I haven't tried this with Jabber. But it works with GMail's SMTP server, so maybe...
Here's how to upgrade a socket to an SSL socket, where socket is the original (non-TLS) connection:
SSLSocket sslSocket = (SSLSocket) ((SSLSocketFactory) SSLSocketFactory.getDefault()).createSocket(
socket,
socket.getInetAddress().getHostAddress(),
socket.getPort(),
true);
InputStream inputStream = sslSocket.getInputStream();
OutputStream outputStream = sslSocket.getOutputStream();
// reads from the socket
Scanner scanner = new Scanner(inputStream);
// writes to the socket
OutputStream outputStream = new BufferedOutputStream(outputStream);

Categories