Looking to get up to speed on Java socket programming?
You’re not alone.
Whether you’re planning to write game console applications or focusing on the benefits of implementing DevSecOps in your processes, knowing more about how sockets work in Java will give you a better understanding of how machines communicate over networks.
In this article, we’ll take a closer look at how to use the Socket class in Java to enable effective and efficient network communication.
What are sockets in Java?
Whether you’re working with cloud PBX platforms or any kind of general network, you’ll need to have an understanding of how sockets work in Java.
Essentially, socket programming enables applications running in separate Java runtime environments to communicate with one another. It’s how a client and a server talk to each other.
If you want a precise definition of a socket, it’s this: one end of a two-way communication link established between two nodes in a network.
In the Java platform, the Socket class is used to create a socket on the network. Achieving the desired network communication will mean setting up both a client socket and a server socket. Each socket is assigned an IP address and a port number. This makes sure the network protocol layer is able to identify the application that data should be sent to.
Using the class instead of native code means that your Java programs will be able to communicate over the network on a platform-independent basis. In terms of microservices Java resources are available that will be of assistance in simplifying the task.
The basic approach is fairly straightforward, however. As long as you understand the way network communication works, you shouldn’t run into too many problems.
If you are using virtual private server hosting such as Ultahost (a VPS in Canada), then you will need to make sure it is compatible with your coding languages.
TCP vs. UDP
There are two methods for achieving network communication: Transport Control Protocol (TCP) and User Datagram Protocol (UDP). They each have their advantages and disadvantages, so the choice of which to use will depend on the nature of the project. One of the many reasons to learn Java is that it will give you plenty of experience in making this kind of decision.
TCP is a reliable protocol that ensures delivery of all information packets. With TCP, both nodes know that the communication payloads have been received. UDP, on the other hand, is connectionless. It’s useful for instances where you don’t need every single packet to be received.
An example of this would be video streaming: UDP is usually used for this. That’s because in this case, ensuring delivery of all packets is not the optimal choice if it means that the client slows down delivery of your video in order to receive every single packet. Far better that a few packets are missing but that speed is maintained. That way, it won’t spoil your enjoyment as a viewer.
So let’s first consider the programming you’ll need to do for the client-side socket.
How client–server communication works is that the client first waits for the server to start and then sends it a request via the connection created between corresponding sockets. The underlying principle is the same in any network, be it for sending print jobs to an office printer or facilitating communication in cloud contact centres.
1. Establish your connection
Step one is to establish a socket connection. This means that the two nodes need to be able to recognise each other’s network location and TCP port.
To create a socket, you start like this:
In this line of code, the first argument represents the client-side socket and the second argument both the IP address of the machine running the server and the TCP port.
2. Implement communication
To actually send information via the connection, you’ll need to obtain input and output streams. This is fairly self-explanatory. Input streams are for reading data from the server and output streams are for writing data to the server.
You can do this by using the input and output stream functions:
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
Bear in mind that these are the same types of streams you would use to read from and write to any file. So they can easily be modified to suit your purposes. For instance, you could wrap the InputStream with a BufferedReader via an InputStreamReader, making it a simple matter to read text with, say, readLine().
3. Closing your connection
Once you’ve established your connection and used it to send requests, you’ll need to close the connection.
When you put it all together, you’ll end up with something like this:
Server-side programming is similar to client-side programming in that you firstly need to establish the connection, then you implement the requests and finish by closing the connection. In the spirit of continuous learning, let’s have a look at the details of this too. Here are the steps you’ll need to take:
1) Firstly, establish a server-side socket using the Socket class:
ServerSocket serverSocket = new ServerSocket(4000);
2) Use the ServerSocket’s accept() method to listen for a connection from the client on the designated port.
3) When a client connects to the server, the accept() method returns a Socket for the server to use to communicate with the client. The process is the same as before: obtain an InputStream to read from the client and an OutputStream to write to it.
4) Again, the argument 4000 here is the port number. The server waits until it receives a connection request at its socket from the client side. Once it does, the following line of code is executed:
Socket clientSocket = serverSocket.accept();
If you’ve done everything correctly, at this point the request is accepted by the server.
In other words, once you’ve completed the configuration of the connection on both the client and server endpoints, you execute the server-side program first. Only after doing that do you run the client-side program in order to send the request. Once the request is sent from the client, the server will respond.
Don’t forget: when writing your Java code, never be afraid of code reuse. It’s a popular habit for a reason. Reusing code that works in new applications is standard practice and it helps speed up the process of new development.
In practice – running the code on a terminal or command prompt
Both the client-side and the server-side Java code will be saved as a .Java file. In UNIX-based systems, these will run on a terminal, while in Windows-based ones, you can run them from the command prompt. When implementing the code this way, follow these steps:
- Step 1: Open your terminal or command prompt.
- Step 2: Make sure to change your path to the directory that contains the Java files for both client and server.
- Step 3: Server first, remember! Use the command $ java server to run the server program.
- Step 4: Run the client program using the command $ java client.
All going well, you should see some text indicating that the client sent its request to the server and that the connection was successfully accepted by the server.
A few words on NIO/NIO.2 and non-blocking APIs
Java is one of the go-to languages for cloud professionals and as such, it is regularly being updated. For basic network communication, the steps we’ve explained so far will be sufficient in most cases. However, there will be some occasions where it’s better to use NIO instead.
The java.nio package was introduced in Java 1.4 before being updated in Java 1.7 (NIO.2). It has enhanced file operation capability and offers the ASynchronousSocketChannel option.
Why would you need to use this? Well, it’s very handy for those situations where you’re dealing with asynchronous input/output.
With NIO, what you can do is open a channel to your destination, then use a buffer. The process involves writing information to a buffer, then reading the data from a buffer, and sending the resulting data to the destination.
In order to use a buffer, you’ll follow these steps:
- Step 1: Write data into a buffer
- Step 2: Call the buffer’s flip() method
- Step 3: Read data from the buffer
- Step 4: Call the buffer’s clear() or compact() method in preparation for it receiving further data
There’s a lot to say about NIO that is outside of the scope of this article, but it’s worth being aware of. It might not be entirely necessary if you’re working on a project like implementing a voice over IP (VoIP) phone system, but it’s part and parcel of modern Java practice.
Making communication work
Whether you’re working on the finer points of Jira HubSpot integration or developing network applications, you may encounter the need to use Java in all sorts of situations.
Hopefully, this introduction to socket programming in Java has whetted your appetite to learn more. If so, we wish you the best of luck on your Java journey!