Friday, February 15, 2013

Java: how to receive unsigned values from a socket connection

Most of developers know that one of the biggest criticism of Java is the lack of native unsigned integer types. For a short discussion about it, see Criticism of Java: Unsigned integer types.

When interfacing a socket connection with a C or C++ written client, you may need to deal with unsigned values, which are widely used in such languages.

It would be nice to (almost) transparently receive UnsignedLong and UnsignedInteger and use it in our Java application.

The following UnsignedDataInputStream Java class tries to fill the gap by extending a DataInputStream in conjunction with the Google Guava libraries capabilities, more specifically with its primitive utilities.

Here is the code:

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;

import com.google.common.primitives.UnsignedInteger;
import com.google.common.primitives.UnsignedLong;

/**
 * 
 * A {@link DataInputStream} able to read unsigned primitive values.
 * 
 * @author Luca Fagioli
 *
 */
public class UnsignedDataInputStream extends DataInputStream {

 public UnsignedDataInputStream(InputStream in) {
  super(in);
 }
 
 /**
  * Reads four input bytes and returns an unsigned integer value.
  * 
  * Bytes for this operation are read from the contained input stream.
  * 
  * @return the next four bytes of this input stream, interpreted as an {@link com.google.common.primitives.UnsignedInteger}.
  * @throws IOException the stream has been closed and the contained input stream does not support reading after close, or another I/O error occurs.
  */
 public UnsignedInteger readUInt() throws IOException {
  
  return UnsignedInteger.asUnsigned(this.readInt());
  
 }
 
 /**
  * Reads eight input bytes and returns an unsigned long value.
  * 
  * Bytes for this operation are read from the contained input stream.
  * 
  * @return the next eight bytes of this input stream, interpreted as an {@link com.google.common.primitives.UnsignedLong}.
  * @throws IOException the stream has been closed and the contained input stream does not support reading after close, or another I/O error occurs.
  */
 public UnsignedLong readULong() throws IOException {
  
  return UnsignedLong.asUnsigned(this.readLong());
  
 }
 
}

You can now accept a socket connection, and be able to receive (almost) flawlessly also unsigned "primitive" values:

int port = 10000;
ServerSocket serverSocket = new ServerSocket(port);

Socket socket = serverSocket.accept();

UnsignedDataInputStream in = new UnsignedDataInputStream(new BufferedInputStream(socket.getInputStream()));

UnsignedInteger uIntValue = in.readUInt();
UnsignedLong uLongValue = in.readULong();

3 comments:

  1. However, you must always keep in mind that a lot of people are out to harm computers everywhere. Getintopc

    ReplyDelete
  2. I have used a lot of juicers in the past and I created this blog to help juice lovers make the right decision in choosing the type of juicer that best fit their needs. There are several good masticating juicers to choose from.  http://www.getinntopc.com

    ReplyDelete