I'm trying to send an image that was taken by my camera in my application as a byte array. I convert the bitmap to byte array, then to Base64 string, then endcode that to a byte array and send. When I try to send it however I get an exception that my string is too long to send.
preparing to send through to socket:
if(currentChatPartner==null)
return;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
msg.compress(Bitmap.CompressFormat.PNG, 0, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream .toByteArray();
String encoded = Base64.encodeToString(byteArray, 0);
sendThroughSocketImage(encoded, clientSocket, currentChatPartner.getIP(), currentChatPartner.getPort());
Sending through to socket:
byte[] decoded = null;
decoded = encoded.getBytes();
try
{
socket.send(new DatagramPacket(decoded, decoded.length, ip, port));
} catch (IOException e)
{
System.err.println("\nUnable to send message");
return false;
}
return true;
Sometimes it works, but most it doesn't :( Is there a reason for this?? Is there a way I could fix it or shorten the string that is to be sent??
By using DatagramPacket you're sending an UDP message that has a miximum length a little short of 64kb. Easy to get a message to long exception. You should send your data using TCP socket.
Plenty of examples online e.g.
http://systembash.com/content/a-simple-java-tcp-server-and-tcp-client/
With respect to your comments, an example of sending the byte array via client socket
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
int start=0;
int len=decoded.length;
OutputStream out = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
dos.write(array, start, len);
Related
I have a Server application on my PC which reads a jpg file and sends it through a socket to the android device. The problem is that when android device receives a byte array, it can't be converted to bitmap. I created a PC application to receive that same array and the data received is different than on the android even though I am using the same code to receive it.
Hence my assumption is that I somehow need to read it differently on android.
PC Java Server
ServerSocket serverSocket = new ServerSocket(PORT);
Socket clientSocket = serverSocket.accept();
BufferedImage image = ImageIO.read(new File("D:\\test1\\test.jpg"));
ByteArrayOutputStream byteArrayoutputStream = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", byteArrayoutputStream);
OutputStream outputStream = clientSocket.getOutputStream();
byte[] size = ByteBuffer.allocate(4).putInt(byteArrayoutputStream.size()).array();
outputStream.write(size);
outputStream.write(byteArrayoutputStream.toByteArray());
outputStream.flush();
Thread.sleep((long)5000);
clientSocket.close();
Android receiver
DataInputStream inputStream = new DataInputStream(serverSocket.getInputStream());
byte[] sizeAr = new byte[4];
inputStream.read(sizeAr);
int size = ByteBuffer.wrap(sizeAr).asIntBuffer().get();
byte[] imageAr = new byte[size];
inputStream.read(imageAr);
System.out.println(imageAr.toString());
bMap = BitmapFactory.decodeByteArray(imageAr, 0, imageAr.length);//this returns null
You probably are not receiving the whole thing,
Instead:
inputStream.read(imageAr);
try:
inputStream.read(imageAr, 0, size);
the second form will wait until size bytes are received.
ADDED
Also do the same on the first read()
instead: inputStream.read(sizeAr); try inputStream.read(sizeAr, 0, 4);
Also get and check inputStream.read() return values, it says how many bytes were really read.
I have a server device and N client devices. I want to send pictures to each client from the server.
My problem is the client doesn't receive the whole image. I converted the Bitmaps to byte array before I send it.
Send Bitmaps on the Server:
try {
OutputStream out = clients.get(i).getSocket().getOutputStream();
//Convert Bitmap to byte array:
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.JPEG, 70, stream);
byte[] byteImage = stream.toByteArray();
//Send the byte array
if(byteImage.length > 0){
out.write(byteImage, 0, byteImage.length);
out.flush();
}
out.close();
} catch (IOException e) {
e.printStackTrace();
}`
Receive image on the Client:
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int length = 0;
while ((length = in.read(data)) != -1) { //in --> InputStream
out.write(data, 0, length);
out.flush();
}
byte[] bytePicture = out.toByteArray();
out.close();
} catch (IOException e) {
}
Before I send the image, I tell the size of the byte array of the Bitmap to the clients.
My problem is the received bytes < send bytes. Why?
On the server side I created threads for all clients to send the images them.
EDIT:
I use PrintWriters to communicate with messages between the server and the clients.
I send the length of the byte array from the server to the clients before I start to send the byte array.
PrintWriter writer;
writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)), true);
writer.println("BYTE#" + byteImage.length);
writer.flush();
When a client get a message, which starts with "BYTE#" on the client side, I start to read the byte array:
reader = new BufferedReader(new InputStreamReader(inputStream));
final String message = reader.readLine();
if (message != null && message.startsWith("BYTE#")){
//Get the length of the byte array (correct)
int length = Integer.valueOf(message.split("#")[1]);
//... Start to read the byte array here...
}
i have a communication App over sockets.
The Client sends an Image to the server:
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
OutputStream os;
try {
os = MyClient.socket.getOutputStream();
os.write(byteArray,0,byteArray.length);
os.flush();
On the server side i want to receive the Image, but at the moments it just shows many different characters. If the Client just sends a text i receive it with:
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
String text = input.readLine();
But how can i "decode" the byte[] on the Server Side?
Analogously to how you sent that image. Simply use an InputStream object like this:
InputStream stream = socket.getInputStream();
byte[] data = new byte[MAX_SIZE];
int count = stream.read(data);
Both objects (sending and receiving) are compatible this way, you just have to know the byte array size, it has to be the same on both places.
I am implementing a p2p application, in which nodes communicate by UDP packet. The packets read from InputStream are sometime not complete.
Here is my code:
...
protected String key;
protected Identifier messId; //Identifier hold a BigInteger
protected String range;
protected String concat;
....
public ReplicationMessage(DataInput in) throws IOException {
fromStream(in);
}
public void fromStream(DataInput in)
try {
super.fromStream(in);
int length=in.readInt();
byte[] data=new byte[length];
in.readFully(data);
concat = new String(data);
System.out.println("concat: "+concat);
messId = new Identifier(in);
} catch (IOException e) {
e.printStackTrace();
}
}
public void toStream(DataOutput out) {
try {
super.toStream(out);
byte[] data = concat.getBytes();
out.writeInt(data.length);
out.write(data);
messId.toStream(out);
} catch (IOException e) {
e.printStackTrace();
}
}
the read packet sometime is complete, for example
concat: 179136678282544:140737488355328
but sometime is not complete, for example
concat: 179136678282544
concat: 179136678282544
concat: 179136678282544
Can any one tell me what the problem is?
Many thanks
Here are the code for sending/receiving the UDP packet
for sending:
private void sendMessage(int comm, Message message, InetAddress ip, int port)
throws IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(bout);
dout.writeInt(comm);
dout.writeByte(message.code());
message.toStream(dout);
dout.close();
byte[] data = bout.toByteArray();
if (data.length > DATAGRAM_BUFFER_SIZE) {
throw new IOException("Message too big, size="+data.length+
" bytes, max="+DATAGRAM_BUFFER_SIZE+" bytes");
}
DatagramPacket packet = new DatagramPacket(data, data.length, ip, port);
socket.send(packet);
}
For receiving the UDP packet
byte[] buffer = new byte[DATAGRAM_BUFFER_SIZE];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
The sending node and receiving node belonging to one machine. the Buffer receiving packet is set to 10*1024 bytes which is much larger than packet length
Here is code for turning incoming datapacket into stream
ByteArrayInputStream bin = new ByteArrayInputStream(packet.getData(),
packet.getOffset(), packet.getLength());
DataInputStream din = new DataInputStream(bin);
int comm = din.readInt();
byte messCode = din.readByte();
Message message = factory.createMessage(messCode, din);
UDP does not deliver damaged or partial packets. Either you aren't sending all the data or you aren't unpacking it properly. You still haven't posted all the code concerned so it is not possible to say exactly where.
I try to send a integer array via datagram socket. What is the best way to accomplish this.
MY sending code is:
public void sendObj(Object obj) {
try{
byteArr = new ByteArrayOutputStream();
objOut = new ObjectOutputStream(byteArr);
objOut.writeObject(obj);
byte[] b = byteArr.toByteArray();
DatagramPacket dgram = new DatagramPacket(b, b.length, InetAddress.getByName("230.0.0.1"), 4446); // multicast
socket.send(dgram);
System.out.println("Package is sent!");
}catch(Exception e){
System.out.println(e.getMessage());
e.printStackTrace();
}
}
And receiving code is:
byte[] b = new byte[65535];
ByteArrayInputStream b_in = new ByteArrayInputStream(b);
DatagramPacket dgram = new DatagramPacket(b, b.length);
socket.receive(dgram); // blocks
ObjectInputStream o_in = new ObjectInputStream(b_in);
Object o = o_in.readObject();
dgram.setLength(b.length); // must reset length field!
b_in.reset(); //
However when I receive it gives StreamException for unknown header value 00000
We solved that problem by a basic changes. We used a string like "100200300..." to symbolize the array by separating element with two 0' so in that way we did not use ArrayList.
You have to use getbyte() method to get the bytes and the put these bytes into a datagram packet instance and then pass it to the client or send it...
Use
arrayName.getBytes(); /// save this into some byte[] temp = new byte[size];
and make a datagram packet and put its argumnets and send it