Sockets & Windows Service - java

theres a guy in my job that connects to a socket thru C using structs of bytes. How can i do the same in Android/Java. I know i can add more info, but i think i need a few answers to develop more into the right point.
Thanks in advance

Read up on the java.net.Socket class.
Upd: getOutputStream() gives you an OutputStream instance. You can write byte arrays directly into it. To simulate C datatypes, you'll have to decompose your variables into bytes using shift and mask operators. For example, to write an int (assuming it's little-endian on the wire), use:
int n;
MyOutStream.write(new byte[]{n&0xff, (n>>8)&0xff, (n>>16)&0xff, (n>>24)&0xff});
For strings, use toByteArray() with the appropriate encoding ("US-ASCII" is not sure).
There's also the DataOutputStream class, which can do the same for you, but IIRC it writes a small header in front of the data, so the wire data will be incompatible with the existing protocol.

Related

java.io.StreamCorruptedException with ruby sender and java client

I have a ruby program that writes data to a socket with sock.write, and I'm reading the data with ObjectInputStream in a java file. I'm getting an invalid header error that translate to the first few characters of my stream.
I've read that if you use ObjectInputStream you must write with ObjectOutputStream, but since the writing file is in ruby im not sure how to accomplish this.
As you say, ObjectInputStream assumes that the bytes it's receiving have been formatted by an ObjectOutputStream. That is, it is expecting the incoming bytes to be a specific representation of a Java primitive or object.
Your Ruby code is unlikely to format bytes in such a way.
You need to define exactly the byte format of the message passing from the Ruby to the Java process. You could tell us more about that message format, but it's likely you will need to use Java's ByteArrayInputStream (https://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayInputStream.html). The data will come into the Java program as a raw array of bytes, and you will need to parse/unpack/process these bytes into whatever objects are appropriate.
Unless performance is critical, you'd probably be best off using JSON or YAML as the intermediate format. They would make it simple to send simple objects such as strings, arrays, and hashes (maps).

Sending many types at the same time with a socket

I want to send a single stream of data corresponding to a couple of different types (say for simplicity one float and one int) from a Socket to another socket (created from a ServerSocket accept()). However, I am not sure what the best way to achieve this is. If I want to use readInt() or readFloat() it seems that I need to send them separately, and I guess that would not be ideal (but please correct me if I am wrong).
The code would start by doing the following (where say the float will be stored in the first 4 bytes in b, and the int will be stored in the last 4 bytes in b)
ServerSocket socket = new ServerSocket(port);
in=new DataInputStream(socket.accept().getInputStream());
byte[] b = new byte[8];
in.read(b);
So far so good, but I would now like to convert only the first four bytes to a float and the last four bytes to an int. I could do something like
float myFloat = ByteBuffer.wrap(b).getFloat();
to get the float, but how do I get the int? In C++ I would just pass the reference to the fifth element in b, but as I understand it this is not possible in java. Of course I could use some library to create a new array from the last four elements of b, but that seems a bit overkill no? or is that the only way?
Any other suggestions on sending many different types at the same time over a socket are greatly appreciated.
I want to send a single stream of data [...] from a Socket to a ServerSocket
Sorry to be nitpicky, but you can't do that. A ServerSocket is a mechanism for accepting connection requests and establishing the local end of a socket-based communication channel. That local end, once established, is represented by a Socket, so what you seem to want to do is send data from Socket to Socket.
But your question seems mainly to be about sending mixed data over the communication channel. In that case, the first question to consider is how the receiver knows what type to attempt to read at any given point. This boils down to having an application-layer communication protocol between the communicating parties. That doesn't have to be formal or grandiose; in your example, there seems to be a shared understanding that the data will be sent as a 32-bit binary float followed by a 32-bit binary int. That's a protocol.
If I want to use readInt() or readFloat() it seems that I need to send them separately, and I guess that would not be ideal
I don't see what you mean. Yes, you do need to know which data are ints and which are floats, but that does not distinguish use of DataInputStream.readInt() and DataInputStream.readFloat() from any other mechanism.
For each datum you transmit, you have two basic alternatives:
count on the receiver to rely on some prior agreement or assumption to determine how to interpret that datum (possibly extending to recognizing the boundaries of its on-the-wire representation), or
along with the datum, transmit metadata that the receiver will use to interpret the datum as intended.
Of course, (2) can be viewed as a special case of (1).
If a message will always consist of one float followed by one int, then I don't see anything wrong with the sender using
myDataOutputStream.writeFloat(f);
myDataOutputStream.writeInt(i);
and the receiver handling that via
myDataInputStream.readFloat(f);
myDataInputStream.readInt(i);
Indeed, for that simple case, I think that's a pretty good choice.
More generally, however, there are many, many other considerations in choosing or designing a communication protocol. A general discussion of that topic would be far too broad for this venue.
Using a Serializable wrapper class for storing values of different types and ObjectInputStream & ObjectOutputStream for reading & writing the class instance seems to be the best way to achieve this. Here and here are good references.

Parse byte array as HTTP object

In Java, how would I convert a byte array (TCP packet payload from a pcap file) into some kind of HTTP object that I can use to get HTTP headers and content body?
One of the stupid lovely things about Java is a total lack of unsigned types. So, a good place to start would be taking your byte array and converting it into a short array to make sure that you don't have any rollover problems. (16 bits versus 8 bits per number).
From there, you could use a BufferedOutputStream to write your data to a file and parse it with one of the Java built-in XML readers, such as JaxB or DOM. BufferedOutputStream writes hex directly to a file, and can take an input of an int, byte, or short array. After you write it out, using the OutputStream it should be very simple to parse the HTML out of it.
If you need any help with any of these individual steps, I'd be happy to help.
EDIT: as maerics has pointed out, perhaps I didn't grasp what you were asking. Regardless, writing your byte array with a BufferedOutputStream is the way to go in my opinion, and I could still help you build a parser if you want.
JNetPcap can do exactly this.
Here are examples for
Opening a pcap file
Parsing http (in the example, we extract an image)
Drawback: parsing http in this library is depracated*, but that doesn't mean it doesn't work
*I can't post anymore links without more reputation. Sorry. You can Google for "jnetpcap http deprecated"

How to read data in Java from a Python Struck.pack

I am using Java UDP datagrampacket to receive a python packet which contains a Struct.pack string. How could I unpack it in Java?
If you have the packet as byte[] array in Java, you can use java.io.java.io.ByteArrayInputStream to create an InputStream from it which can be wrapped by java.io.DataInputStream which provides methods to read several simple datatypes.
Be aware that DataInputStream works with big endian. If you use little endian some byte juggling will be necessary for multi-byte integer types.

Java and Binary data in the context of sockets

Java newbie here. Are there any helper functions to serialize data in and out of byte arrays? I am writing a Java package that implements a network protocol. So I have to write some typical variables like a version (1byte), sequence Number (long) and binary data (bytes) in a loop. How do I do this in Java? Coming from C I am thinking of creating a byte array of the required size and then since there is no memcpy() I am converting the long into a temporary byte array and then copying it into the actual byte array. It seems so inefficient and also really error prone. Is there a class I could use to marshall and unmarshall parameters to a byte array?
Also why does all the Socket classes only deals with char[] and not byte[]? A socket by definition has to deal with binary data also. How is this done in Java?
I am sure what I am missing is the Java mindset. Appreciate it if some one can point it to me.
EDIT: I did look at DataOutputStream and DataInputStream but I cannot convert the bytes to a String not to a byte[] which means the information might be lost in the conversion to write to a socket.
Pav
Have a look at DataInputStream, DataOutputStream, ObjectInputStream and ObjectOutputStream. Check first if the layout of the data is acceptable to you. Also, Serialization.
Sockets neither deal with char[] nor with byte[] but with InputStream and OutputStream which are used to read and write bytes.
If you are sending the data over a socket, then you don't need a temporary byte array at all; you can wrap the socket's OutputStream with DataOutputStream or ObjectOutputStream and just write what you want to write.
There might be an aspect I've missed that means you do actually need temporary byte arrays. If so, look at ByteArrayOutputStream. Also, there's no memcpy(), sure, but there is System.arraycopy.
As above, DataInputStream and DataOutputStream are exactly what you are looking for. Re your comment about String, if you're planning to use Java Strings over the wire, you're not designing a network protocol, youre designing a Java protocol. There are readUTF() and writeUTF() if you're sure the other end is Java or if you can code the other end to understand these formats. Or you can send as bytes along with the appropriate charset, or predefine the charset for the entire protocol if that makes sense.

Categories