I have a big problem....
We have a project on school and work as dou.
I write the go server and my partner the java client.
I have a problem that if he is sending something like: "Hello World" the golang server split this into "Hello" and "World"
See Picture
The Java Code:
public class DataController {
public String recieveDataFromServer(Socket socket) throws Exception {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (!bufferedReader.ready()) { }
String data = bufferedReader.readLine();
return data;
}
public void sendDataToServer(Socket socket, String data) throws Exception
{
PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
printWriter.println(data);
}
}
The go Code:
func handleRequest(conn net.Conn) {
request := make([]byte, 256)
for {
_, err := conn.Read(request)
if err != nil {
Error.Println(err.Error())
return
}
Info.Println("Message Received: " + string(request))
message := []byte(time.Now().String())
message = append(message, []byte(": ")...)
message = append(message, request...)
broadcast(message)
}
}
The broadcast function just do a conn.Write(msg) for all the connections.
Does anyone know that the problem is?
Edit: I found the problem. Java add after each word a \r\n. Then the go server think the message ended. We switch now to c#. its easier and work correct while writing with a bufferedWriter to a socket.
You maybe need send first the number of bytes to read and later the bytes to read with io.ReadFull function... of this way you are sure that read all the string...
ReadFull in go https://golang.org/pkg/io/https://golang.org/pkg/io/
ReadFully Java with DataInputStream : https://docs.oracle.com/javase/8/docs/api/
First read int with the number of bytes....
Later read bytes with io.ReadFull method...
NOTE : You need write the integers in bigendianess to java.
binary.Write(tx, binary.BigEndian, value)
My advice make the complex in go and read int and readFull bytes in java...
NOTE : You can only simple write bytes in both directions if you need send images or some similar...
Code to send and write bytes in Go
Code to send and write bytes in Java
I hope this help...
In this case i will suggest to use gRPC. here is the documentation
and here is gitrepo.
Use protobuf instead of JSON to define the contract of service.
So you can use this service for other clients as well which may be in any language.
and for implementing this you just need to extract your service contract and generate your contract in client respective language.
May be its little expensive in term of building but it will make your project reusable and definately you will learn something new.
Related
I am trying to send encrypted data between a client and server. Due to the RSA encryption its in Byte array form. This means I have had to change the way I send data. I curently cant get it working, Ill leave my method (sendMessage) below which is what handles the sending of the message, If anyone could tell me what I am doing wrong that would be great :)
public void sendMessage(byte[] msg){
if(msg.equals("null")){
}
else{
try{
ByteArrayOutputStream f = new ByteArrayOutputStream(CSocket.getOutputStream());
out = new PrintWriter(f);
out.write(msg);
countSend++;
}catch (IOException e){
System.out.println("ERROR");
}
}
}
Sorry should have clarified, essentially CSocket is a socket I have opend and I want to send msg through the socket. The issue I have specifically with this code is It says that: OutputStream can not be converted to int on the line where I creat the ByteArrayOutputStream object f and No suitable method found for write(byte[]) on the line out.write(msg);
Thanks for the clarification! Please see https://docs.oracle.com/javase/10/docs/api/java/io/ByteArrayOutputStream.html#write(byte%5B%5D,int,int)
The write method in ByteArrayOutputStream for byte[] needs two more arguments. Something like the following might work:
out.write(msg, 0, msg.length);
Please let me know if this is useful.
I think I fixed my issue now. Its probibably not the most efficient way of doing it but essentially I encode the byte array in a format that means I wont loose any data. This means I send it in this encoded format and then on the receving end I just simply decode it. Works so much better with print writer doing it this way.
OutputStream f = CSocket.getOutputStream();
out = new PrintWriter(f);
String encodedmsg = new String(msg, "ISO-8859-1"); // ISO-8859-1 is supposed to give every character a unique representation so I shouldent loose any data during encoding and decoding
out.write(encodedmsg);
I'm trying to get some data from the com port, the same one I'm writing data on, but it proves hard to read. I managed to find a simple code piece to read it, but now, I only read zeros. What could be the cause?
I'm sending my code below, with explanation of their intended usages.
private void ReadFromComPortActionPerformed(java.awt.event.ActionEvent evt) {
try {
String text = EmulatorInput.getText();
sendData(text, "COM4");
String out_Text = Arrays.toString(read());
EmulatorOutput.setText(out_Text);
System.out.println(out_Text);
} catch (IOException ex) {
Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
}
}
This is a JButton, method name and parameter has been created by NetBeans. Code firsts gets a text from the input panel as a string, sends it with a com port name, connects to that port, and opens input/output streams by it, then writes the string it took from the input panel to the OutputStream. Then, I create a new string, named out_Text and use read() method to read the data from port.
Here is the read method;
private byte[] read() throws IOException {
byte[] buffer = new byte[16];
int total = 0, read = 0;
while (total <= 16 && (read = input.read(buffer, total, 16-total)) > 0) {
total += read;
}
return buffer;
}
After the first method I posted uses read() to converge it into a string that I can print as a byte array, I end up with only a byte of zeros.
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
I'm very confused by this, because I'm sure I write to the port. I even monitored what I write, and can see that as I use the program to write data to the com port, the data it received increases.
If there is something that is unclear or if you need more of the code, please contact via comments.
Thank you kindly.
After several tries, I've tried the same operation with jSSC, and managed to write again. However, I was still not able to read. Then I noticed, that I was creating pairs of com ports. So, simply, I started to write to one port, and received the data from the other port of the pair. It worked like a charm. I'm not sure if the same idea is valid for rxtx libraries, but because jSSC's documents are descriptive, and because it's easy to use, I switched to it, and the way I did worked. You can find a detailed explanation of how I did below, without the code.
PreStep > I had COM6 and COM7 intact when I started this.
Step1 > Opened both ports via jSSC's methods. I constructed them as SerialPort, and then set their parameters (BaudRate, DataBits, etc.).
Step2 > I started to take inputs from console, and write them to the COM6. When I monitored the port, and the bytes in it, it was changing each time I sent an input.
Step3 > Each time I would press "Enter" to send the input, I'd invoke a reading method from COM7 object, and it would send a byte array to the console (Via Arrays.toString(byte[] array) method).
I don't know why I can't read from the same port as I write, but alas, my problem is solved. Thanks for your time to read this answer. If you have any questions, please post them under this one as a comment.
I've been reading up a lot on Iteratees & Enumerators in order to implement a new module in my application.
I'm now at a point where I'm integrating with a 3rd party Java library, and am stuck at working with this method:
public Email addAttachment(String name, InputStream file) throws IOException {
this.attachments.put(name, file);
return this;
}
What I have in my API is the body returned from a WS HTTP call that is an Enumerator[Array[Byte]].
I am wondering now how to write an Iteratee that would process the chunks of Array[Bytes] and create an InputStream to use in this method.
(Side bar): There are other versions of the addAttachment method that take java.io.File however I want to avoid writing to the disk in this operation, and would rather deal with streams.
I attempted to start by writing something like this:
Iteratee.foreach[Array[Byte]] { bytes =>
???
}
However I'm not sure how to interact with the java InputStream here. I found something called a ByteArrayInputStream however that takes the entire Array[Byte] in its constructor, which I'm not sure would work in this scenario as I'm working with chunks ?
I probably need some Java help here!
Thanks for any help in advance.
If I'm following you, I think you want to work with PipedInputStream and PipedOutputStream:
https://docs.oracle.com/javase/8/docs/api/java/io/PipedInputStream.html
You always use them in pairs. You can construct the pair like so:
PipedInputStream in = new PipedInputStream(); //can also specify a buffer size
PipedOutputStream out = new PipedOutputSream(in);
Pass the input stream to the API, and in your own code iterate through your chucks and write your bytes.
The only caveat is that you need to read/write in separate threads. In your case, its probably good to do your iterating / writing in a separate thread. I'm sure you can handle it in Scala better than me, in Java it would be something like:
PipedInputStream in = new PipedInputStream(); //can also specify a buffer size
PipedOutputStream out = new PipedOutputSream(out);
new Thread(() -> {
// do your looping in here, write to 'out'
out.close();
}).run();
email.addAttachment(in);
email.send();
in.close();
(Leaving out exception handling & resource handling for clarity)
I am trying to write a server that accepts files and write it in certain directory using DataInputStream and BufferedInputStream.
The server gets 'user name(string)' 'number of files(int)' 'file name(string)' 'size of each file(long)' and 'contents of file which is uninterpreted bytes(byte[])'
and if everything is successful then, I am supposed to send boolean value.
But the problem is that it is not receiving file correctly.
From time to time I get 'broken pipe' error message or the file is corrupted after I receive.
I looked at my code for 4hrs and couldn't find the problem.
Would you please help me about this?
You can assume that client is working fine.
FIrst you don't have to close all of those streams. That's probably why you're seeing the broken pipe problem. You just need to close the input and output stream.
DataInputStream din = new DataInputStream( new BufferedInputStream( socket.getInputStream() ) );
DataOutputStream dout = new DateOutputStream( new BufferedOutputStream( socket.getOutputStream() );
try {
} finally {
din.close();
dout.close();
}
The reason you don't have to close all of those streams is because your Buffered*Streams and socket InputStream/OutStream will be closed when din/dout.close() is called. Those will close the streams through the reference they chain to. You can also get rid of all that if( blah != null ) junk on each of those because if you make it to the finally clause you know they are non-null. You know that's the case if you don't new up inside the try.
You're also leaking your FileOutputStream because you overwrote the fos variable with the second new FileOutputStream(). What are you doing there with the SUBMIT_DONE file? That's truly weird. It's pretty bad idea to do that. Don't use variable references twice like that. I would probably close the first file after your loop. Think about wrapping that loop with try {} finally { fos.close(); }.
And you might try using methods to break this up a little. Ditch the static.
Update:
What exactly do you think the following is doing?
while(c!='\0') {
userName += c;
c = din.readChar();
}
Depending on how you are sending the data from your client or server you could just use:
String userName = din.readUTF();
Remember with DataInputStream you are processing formatted BINARY data. You also have that exact loop code repeated again for the filenames. If you can't use readUTF() then create a method that wraps up that loop and returns a string and call it from those two places. You have all sorts of security issues allowing clients to upload raw filenames and files to you. I hope to sweet baby jeez this server you're building isn't being deployed in production.
You also need to flush and close each file you receive over the socket so the full amount of data sent is completely written to the files.
We are streaming data between a server (written in .Net running on Windows) to a client (written in Java running on Ubuntu) in batches. The data is in XML format. Occasionally the Java client throws an unexpected EOF while trying decompress the stream. The message content always varies and is user driven. The response from the client is also compressed using GZip. This never fails and seems to be rock solid. The response from the client is controlled by the system.
Is there a chance that some arrangement of characters or some special characters are creating false EOF markers? Could it be white-space related? Is GZip suitable for compressing XML?
I am assuming that the code to read and write from the input/output streams works because we only occasionally gets this exception and when we inspect the user data at the time there seems to be special characters (which is why I asked the question) such as the '#' sign.
Any ideas?
UPDATE:
The actual code as requested. I thought it wasn't this due to the fact that I had been to a couple of sites to get help on this issue and they all more or less had the same code. Some sites mentioned appended GZip. Something to do with GZip creating multiple segments?
public String receive() throws IOException {
byte[] buffer = new byte[8192];
ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
do {
int nrBytes = in.read(buffer);
if (nrBytes > 0) {
baos.write(buffer, 0, nrBytes);
}
} while (in.available() > 0);
return compressor.decompress(baos.toByteArray());
}
public String decompress(byte[] data) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ByteArrayInputStream in = new ByteArrayInputStream(data);
try {
GZIPInputStream inflater = new GZIPInputStream(in);
byte[] byteBuffer = new byte[8192];
int r;
while((r = inflater.read(byteBuffer)) > 0 ) {
buffer.write(byteBuffer, 0, r);
}
} catch (IOException e) {
log.error("Could not decompress stream", e);
throw e;
}
return new String(buffer.toByteArray());
}
At first I thought there must be something wrong with the way that I am reading in the stream and I thought perhaps I am not looping properly. I then generated a ton of data to be streamed and checked that it was looping. Also the fact they it happens so seldom and so far has not been reproducable lead me to believe that it was the content rather than the scenario. But at this point I am totally baffled and for all I know it is the code.
Thanks again everyone.
Update 2:
As requested the .Net code:
Dim DataToCompress = Encoding.UTF8.GetBytes(Data)
Dim CompressedData = Compress(DataToCompress)
To get the raw data into bytes. And then it gets compressed
Private Function Compress(ByVal Data As Byte()) As Byte()
Try
Using MS = New MemoryStream()
Using Compression = New GZipStream(MS, CompressionMode.Compress)
Compression.Write(Data, 0, Data.Length)
Compression.Flush()
Compression.Close()
Return MS.ToArray()
End Using
End Using
Catch ex As Exception
Log.Error("Error trying to compress data", ex)
Throw
End Try
End Function
Update 3: Also added more java code. the in variable is the InputStream return from socket.getInputStream()
It certainly shouldn't be due to the data involved - the streams deal with binary data, so that shouldn't make any odds at all.
However, without seeing your code, it's hard to say for sure. My first port of call would be to check anywhere that you're using InputStream.read() - check that you're using the return value correctly, rather than assuming a single call to read() will fill the buffer.
If you could provide some code, that would help a lot...
I would suspect that for some reason the data is altered underway, by treating it as text, not as binary, so it may either be \n conversions or a codepage alteration.
How is the gzipped stream transferred between the two systems?
It is not pssible. EOF in TCP is delivered as an out of band FIN segment, not via the data.