how to stream jpeg frame from java client to python server - java

i am developing an android application wherein i have to send a frame in jpeg format allocated to a BufferedArrayOutputStream (baos variable in code). I convert this baos into a byte array to write into the socket.
On the server side i would like to reconstruct the image in jpeg format. If i write the data received in a variable to a '.jpg' file on the server, on opening the file, it gives an error like "file starting with ffx0 not jpeg format". I think this is because the string variable in python writes the data in the file as a hex string.
The client code is as follows :-
Bitmap memoryImage = Bitmap.createBitmap(rgb, previewSize.width,previewSize.height,Bitmap.Config.ARGB_8888);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if(memoryImage.compress(CompressFormat.JPEG,100, baos)){
try {
if(count==0){
byte [] Finalbaos = baos.toByteArray();
int tempLen = Finalbaos.length;
Log.v("Client","ImageBytes :"+ tempLen);
String dataMeta = Integer.toString(tempLen);
Log.v("Client","Integer Size :"+ dataMeta.length());
PrintWriter tempOut = new PrintWriter(socket.getOutputStream());
if(tempOut!=null){
tempOut.write(dataMeta);
Log.v("Client","data size sent");
tempOut.flush();
}
DataInputStream in = new DataInputStream(socket.getInputStream());
if(in!=null){
Log.v("Client","read buffer created");
String xyz = in.readLine();
String temp = "recvd";
Log.v("Client",xyz);
if(xyz.equals(temp)){
OutputStream out = socket.getOutputStream();
out.write(Finalbaos,0,tempLen);
out.flush();
Log.d("Client", "Client sent message");
}
}
server code:
import socket,thread
import string
import array
host=""
port=54321
s=socket.socket()
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind((host,port))
s.listen(5)
conn,address=s.accept()
data=""
mylen=0
dataRecv=0
file1 = open("myfile.jpg","w")
totalLength=""
length=conn.recv(1024)
conn.send("recvd")
mylen=int(length)
while dataRecv<mylen:
newData=""
newData=conn.recv(1)
if not newData:
break
data+=newData
dataRecv+=len(newData)
result= array.array('B',data.decode("hex"))
file1.write(result)
file1.close()
print len(data)
conn.close()
s.close()
can anyone let me know how to reconstruct the frame on server either in python or C++

mylen=len(length) doesn't give you the length you're trying to send. it gives you how many bytes were read in the previsous recv. So you get the wrong lenght there.
on your client side, you use String xyz = in.readLine(); which will block until a newline character is encountered. but you never send a '\n' on the server side, instead you go waiting for a response from the client. so you have a deadlock there.
you use data.decode("hex") on your recieved data. unless you do the equivalend of data.encode("hex") in java on the other side, that won't work. it should give you an error if the string is not a valid hex-representation of a binary string.
result is an array.array, which you write to file. file1.write expects a string as argument, it gives you an error if you pass your result object.
so i can't even see why your code works at all, and why there's anything at all in your file.

Related

How send the http post request with DataOutPutStream properly so server can handle it

I wish somebody tell me what is the different of just write a file and a file with another kind of bytes.
server using, python3 flask
I think maybe the android retrofit etc useful, but I would like to try with the classic method, HTTPUrlConnection
So i successfully sending just one or multi-parameter of string to the server.
I also successfully just by sending a file to the server.
- my file will just 5-second audio or video mp4 that creates from real android.
When i tried just two, param and a list of byte, len(list) = 2, i can get back my sent file, but the concat style of the bytes just could not acheive it.
but when I combine both of it, i found out that when the file is chopped as multi-part, the file just could not recover.
I know delimeter is useful, I tried with a string of "--------------" to split it in server-side.
list= request.data.split(b"------------------------------")
newList= list[1:]
data = b""
for part in newList:
data += part
how i recover the file (python)
def createAudioFromDataReceived(fileName, data):
with open(fileName, 'wb') as wfile:
wfile.write(data)
the basic code write to dataOutPutStream
public void writeFilesParamToDataOutputStream(HttpURLConnection conn, File file, String action) throws IOException {
byte[] buffer;
FileInputStream fileInputStream = new FileInputStream(file);
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
buffer = new byte[1024 * 1024];
int length = 0;
while ( ( length = fileInputStream.read( buffer ) ) > 0 ) {
dos.write(buffer, 0, length);
}
dos.flush();
fileInputStream.close();
dos.close();
}
to add extra line to the dataOutputStream
//Bytes
byte[] bytes = "toSend".getBytes();
dos.write(bytes);
dos.write("------------------------------");
ops, reference are seen before
roughly this kind How to send data from server to Android?
i could not imagine the byte got alot of "-" and need "/r/n" ...
delimiter should be some thing like
String delimiter = "--aaWEdFXvDF--" + "\r\n";

GZIPInputStream unable to decode at receiver side (invalid code lengths set)

I'm attempting to encode a String in a client using GZIPOutputStream then decoding the String in a server using GZIPOutputStream.
The client's side code (after the initial socket connection establishment) is:
// ... Establishing connection, getting a socket object.
// ... Now proceeding to send data using that socket:
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
String message = "Hello World!";
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(out);
gzip.write(message);
gzip.close();
String encMessage = out.toString();
out.writeInt(encMessage.getBytes().length);
out.write(encMessage.getBytes());
out.flush();
And the server's side code (again, after establishing a connection):
DataInputStream input = new DataInputStream(socket.getInputStream());
int length = input.readInt();
byte[] buffer = new byte[length];
input.readFully(buffer);
GZIPInputStream gz = new GZIPInputStream(new ByteArrayInputStream(buffer));
BufferedReader r = new BufferedReader(new InputStreamReader(gz));
String s = "";
String line;
while ((line = r.readLine()) != null)
{
s += line;
}
I checked and the buffer length (i.e., the coded message's size) is passed correctly, so the right number of bytes is transferred.
However, I'm getting this:
java.util.zip.ZipException: invalid code lengths set
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:164)
at java.util.zip.GZIPInputStream.read(GZIPInputStream.java:117)
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:122)
at parsing.ReceiveResponsesTest$TestReceiver.run(ReceiveResponsesTest.java:147)
at java.lang.Thread.run(Thread.java:745)
Any ideas?
Thanks in advance for any assistance!
You're calling toString() on the ByteArrayOutputStream - that is incorrect, and it opens up all kinds of character encoding problems that are probably biting you here. You need to call toByteArray instead:
byte[] encMessage = out.toByteArray();
out.writeInt(encMessage.length);
out.write(encMessage);
Detail:
if you use toString(), Java will encode your bytes in your platform default character encoding. That could be some Windows codepage, UTF-8, or whatnot.
However not all characters can be encoded properly, and some will be replaced by an alternative character - a question mark perhaps. Without knowing the details, it's hard to tell.
But in any case, encoding the byte array to a String, and then decoding it to a byte array again when you write it out, is very likely to change the data in the byte array. And there is not need to do it, you can just get the byte array straight away as shown in the code above.
Why on earth are you indulging in all this complication? You can reduce it all to this:
GZIPOutputStream gzip = new GZIPOutputStream(socket.getOutputStream());
DataOutputStream out = new DataOutputStream(gzip);
String message = "Hello World!";
out.writeUTF(message);
out.close();
// ...
GZIPInputStream gz = new GZIPInputStream(new ByteArrayInputStream(socket.getInputStream()));
DataInputStream input = new DataInputStream(gz);
String line = input.readUTF();
I further note that your code doesn't actually compile. I would further note that unless the messages are several orders of magnitude larger, there is no benefit to the GZipping.

Byte array reading

I have a problem with writing an reading an array of bytes from client to server. The client actually writes all the bytes but the server does not seem to be able to read it. Here is the code for the client and server sides
Socket sock = new Socket(Interface.SERVER_IP, 4444);
PrintStream os = new PrintStream(sock.getOutputStream());
os.println("3");
DataOutputStream dOut = new DataOutputStream(sock.getOutputStream());
dOut.writeInt(data.length); // byte array created above
dOut.write(data);
and the server side is:
DataInputStream clientData = new DataInputStream(clientSocket.getInputStream());
int length = clientData.readInt();
System.out.println(length);
byte[] data = new byte[length]; // read length of incoming message
if(length>0) {
clientData.readFully(data, 0, data.length); // read the message
}
The server seems to be blocked at the line to read the length of the byte array. Please I really need help solving this
After you write the data, flush the output:
dOut.writeInt(data.length); // byte array created above
dOut.write(data);
dOut.flush();
Alternatively, close the stream (if you aren't going to use it again)...
dOut.writeInt(data.length); // byte array created above
dOut.write(data);
dOut.close();
Also note that your PrintWriter is printing a string value (of "3"). You are printing extra data to the stream that doesn't seem to get consumed on the server.
You're printing "3" to the socket but you're never reading it. So when you do readInt(), you're reading the "3" and a line terminator instead.
Don't mix multiple streams/writers on the same socket. Use the same ones for the life of the socket.

Java PrintWriter Not sending Byte Array

A byte array of unknown size is needed to be sent over a socket. When i try to write the byte array to printwriter like
writeServer = new PrintWriter(socketconnection.getOutputStream());
writeServer.flush();
writeServer.println("Hello World");
writeServer.println(byteArray.toString());
It is received at the server but is only a string of 5-6 characters always starting from [B#..... But when i send it through the output stream like
writeServer.println("Hello World");
socketconnection.getOutputStream().write(byteArray);
It is received at the server correctly. But the issue is in the second option the "Hello World" String does not go through to the server. I want both of things delivered to the server.
How should i do it?
You are trying to mix binary and text which is bound to be confusing. I suggest you use one or the other.
// as text
PrintWriter pw = new PrintWriter(socketconnection.getOutputStream());
pw.println("Hello World");
pw.println(new String(byteArray, charSet);
pw.flush();
or
// as binary
BufferedOutputStream out = socketconnection.getOutputStream();
out.write("Hello World\n".getBytes(charSet));
out.write(byteArray);
out.write(`\n`);
out.flush();
byteArray.toString() will return you human readable form of byteArray. Even though for Arrays it is never human readable.
If you want to transfer byteArray as String then you should use
String str = new String(bytes, Charset.defaultCharset());//Specify different charset value if required.

File transfer and object serialization in Java

Im working on a Client/server chat application which allows user to send files (images / videos...) through a socket connection.
In order to manage all kind of communication, I use an Object "Packet" which stores all information that I want to send. (Sender, receivers, file ...).
Here is a code sample where I write in the stream :
private void write(Packet packet) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(bos);
os.writeObject(packet);
this.outStream.write(bos.toByteArray());
}
And outStream is an OutputStream.
Here is my Connection run :
public void run() {
while (isRunning()) {
try {
byte[] buffer = new byte[65536];
// Read from the InputStream
inStream.read(buffer);
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buffer));
Packet p = (Packet) in.readObject();
} catch (IOException e) {
e.printStackTrace();
this.disconnect();
}
}
}
It works very well for all purpose except files transfer !
I put the file in a byte[] (with filestream) and store the array in my Packet Object.
When the server receive the communication it breaks on the "in.readObject()" and give me a pretty "java io streamcorruptedexception wrong format : 0" exception.
I tried the transfer with a custom byte[] (filled by a string.getBytes()) and it worked very well.
So, what am I doing wrong ?
You're reading from the InputStream to a byte array (with an arbitrary size which could be too small). Then you construct an ObjectInputStream to read from this byte array. Why don't you read your object directly from the InputStream?
ObjectInputStream in = new ObjectInputStream(inStream);
Packet p = (Packet) in.readObject();
No need for a buffer.
Moreover, InputStream.read() doesn't read everything from the InputStream. It reads what is available, and returns the number of bytes read. If you don't loop until it returns -1, you only read a part of what has been sent on the other side.
BTW, you're doing the same mistake on the sending side. Instead of writing your object directly to the output stream, you write it to a byte array, adn then send this byte array. Write your object directly to the stream:
ObjectOutputStream os = new ObjectOutputStream(this.outputStream);
os.writeObject(packet);
No need for a buffer.

Categories

Resources