aspose file tools*
The moose likes Sockets and Internet Protocols and the fly likes Image transfer through sockets Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Sockets and Internet Protocols
Bookmark "Image transfer through sockets" Watch "Image transfer through sockets" New topic
Author

Image transfer through sockets

Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
Hey all,

Im trying to send an image over a socket connection. I have been looking at an example in a previos thread here on Java Ranch:

web page

I dont know where/how I insert my image. I think i need a Buffered image.

Help welcome!
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

In that example anirudh was manipulating the GIF image so he'd have a BufferedImage instance. If you're just moving the file from one place to another, forget about ObjectInputStream and ObjectOutputStream. Just open the file with a FileInputStream and write it to the socket's InputStream. On the client, do the reverse: socket's OutputStream -> FileInputStream.


"blabbing like a narcissistic fool with a superiority complex" ~ N.A.
[How To Ask Questions On JavaRanch]
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
Hey Joe,

I tried what you said...

Originally posted by Joe Ess:
Just open the file with a FileInputStream and write it to the socket's InputStream. On the client, do the reverse: socket's OutputStream -> FileInputStream.


But I still cant get it to send. I am getting a read failed message on the server when I try and write the image back to a file. I have a print statement to see what is being sent.

java.io.FileInputStream@7d5d2a

Im sure Im still not doing something right. Any further tips?
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

You don't actually write the stream itself. You read FROM the input stream and write TO the output stream. Something like this example from the Java IO Tutorial:
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
Joe,

I got it sending information to the server. I am printing out the information being sent. But nothing is going into the file. Here is the part of the code to send the file. Im not sure this is correct...


and here is the bit that prints it out and writes it to file...

Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

Originally posted by Dan Lynch:
[QB]


Like I said above, you don't write the input stream instance to the output stream. You READ from the input stream and WRITE to the output stream. You did it on the server side correctly (except for using a Writer, as noted below).
I see you are using out.println() to write the data to the socket. Dont. It will introduce new lines into the data, which will cause havoc in a GIF. That means whatever you declared out to be is inappropriate for binary data.
My example above wasn't the best. Readers and Writers are specialized streams for use with character-based data. You want to use Streams, which don't do character conversion on the data. The same example as above, done with Streams, from the Java Tutorial:


You should take a gander at the Java IO Tutorial. Java IO is not easy to grasp at first, but once you do, you can use the same classes to do IO on sockets, files, databases, URL's. Pretty much everything.
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
Joe,

Im another step closer...I think. I have it now sending information. The problem is that its mixing up the information, or so it seems. Here are the bytes on both sides.

Client..255 216 255 224 0 16 74 70 73 70 0 1 1 1 0 72 0 72 0 0 255 219 0 67 0 5 3 4 4 4 3 5 4 4 4 5 5 5 6 7 12 8 7 7 7 7 15 11 11

Server.. 255 255 0 74 73 0 1 0 0 0 255 0 0 3 4 3 4 4 5 6 12 7 7 15 11 12 15 18 15 17

The client is where the file comes from. As you can see the sequence isnt followed. Am I still missing some step.

Cheers
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

It's hard to diagnose with just the bytes. How's about showing us the current version of the code above?
David Harkness
Ranch Hand

Joined: Aug 07, 2003
Posts: 1646
Did you notice the pattern? The server is seeing every other byte. That should be a big help in diagnosing the problem in the code. I expect to see something like the following or something similar.
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
David and Joe,

Thanks again. You were right David.



I also noticed before that all the information is not being sent to the server. The server code does not print out STUFF and the number of bytes. Am I sending the information badly by sending every byte on their own. Is there some kind of limit to the amount of informatin being sent. Ill include the client code so you can see whats happening.


[ April 28, 2005: Message edited by: Dan Lynch ]
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
Hey,

Ive got it sending properly now. The image is messed up though. Is there anything I can do about this?

Dan
David Harkness
Ranch Hand

Joined: Aug 07, 2003
Posts: 1646
You have other options instead of sending the image byte-by-byte. To improve performance, you want to send larger chunks (big effect) and minimize the number of method calls (minor effect on modern hardware).

To send and receive chunks for a big performance gain, wrap the input/output streams with their buffered cousins: BufferedInput/OutputStream. Even if you write out one byte at a time, the buffered stream won't write to the underlying stream until its buffer is full. For example, a buffer size of 2000 bytes would accept 2000 write(byte) calls before actually writing to the network or file, and then it would write the entire buffer at once.*

Similar to sending chunks, use the write(byte[]) and read(byte[]) methods to operate on entire arrays of bytes rather than single bytes. Be forewarned, though, that read(byte[]) returns the number of bytes actually read, meaning that it may not fill the full array. For writing the possibly partial array to the file's output stream, you'll find write(byte[], offset, length) helpful; length here would be the value returned from read().

Buffering is pretty much essential for good performance, and using the byte array methods, while slightly more complicated, is standard practice and gives its own performance boost. I highly recommend combining the two.

By the way, Sun has a great I/O tutorial that will cover these topics much better than a single post can. As well, they include excellent sample code that you can adapt to your needs for copying from one stream to another.

Finally, if you are using JDK 1.4 or later and want to learn something really cool, check out New I/O (a.k.a. Merlin). Sun and IBM's DeveloperWorks again have great tutorials.

Let us know if you hit any snags or need further clarification, but I highly recommend the tutorials for quick learning. After going through them you'll be able to get much farther before needing help, and the questions you'll have will be more easily answered on this forum.
David Harkness
Ranch Hand

Joined: Aug 07, 2003
Posts: 1646
Originally posted by Dan Lynch:
The image is messed up though. Is there anything I can do about this?
No, images are always messed up when sent over networks. Seriously, this should be fixable if you can describe how the image is messed up. Open the file in a text editor that has a hex mode and compare it to the bytes you are receiving on the server side.

If there's no difference, post your latest server code, and let's see what we can find.

Note: Can you please fix your previous post that begins "David and Joe" to close the first CODE tag after the "output.close();" line so that the following paragraph wraps correctly. This page is getting a bit difficult to read. Thanks!
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
Thanks David.

I've been printing out the bytes after they are sent and before. It seems that the bytes that are altered are changed to 63 hex. I should be able to get the byte resent fairly easily.

Cheers
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

I warned you about using a FileWriter on your server side, but did you listen? They are only for use with character data. Use a FileOutputStream on your server side and all will be well (knocking on wood).
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
Joe,

I I found that earlier and changed it. It sends but the issue of bytes changing still exists.

Dan
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

Let's see the code you are working with now.
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
server code is the same except that Ive corrected the FileWriter part.



Do I have to do sth else on the server side to make sure the info is ok?
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

I don't see anything obvious. Is "in" just an InputStream initalized with Socket.getInputStream()?
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
Yeah. In is a BufferedReader



I think Ill write something to check the bytes. All the changed ones seem to be changed to 63 so Ill use that as a start point.
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

Don't use readers to read binary data!
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
Ok now its



But its still corrupting the data.
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
Hey all,

Im sorry for taking this many posts to sort this out. I re-read something earlier and I saw that I was sending the information using the PrintWriter. I changed this to a bufferedOutputStream and it working. Thanks a million for all the help.
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

I took your code above and wrapped it with a class declaration and it worked fine. The only thing I did that you didn't show above was flush my client's output stream before closing it. Now if I use a buffered reader like you were on the server side, it mucks up the image. There must be something we're not seeing. Let's see all your code.
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
Hey,

Ive got it working now. Sorry it took so long. Now that Im using the proper streams is there any reason why when I send large images 50KB + the socket resets. And Ive sent an image thats 9KB and it has lost over 300 bytes (9039-8704). Is there anything I can do about this?

Cheers
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

Do you flush the client side output stream before closing it?
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
I did flush the output stream. The server is crashing with this error.

java.net.SocketException: Connection reset by peer: JVM_recv in socket input stream read

Do I need to flush anything on the serverside?
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
should say the server crashes with the above error when I try and send an image over 9KB
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

Interesting. The default size for the buffer in a BufferedInputStream is 8192k. Try it without the BufferedInputStream on the server side of the socket. My wild-assed theory is that when the client finishes writing and closes the socket, the server-side stream gets flagged as closed. When the server-side BufferedInputStream goes back to the socket for the second buffer-sized chunk, the socket throws a "connection reset" even though there's still data to be read.
Disclaimer: The above contains wild speculation based upon the behavior at hand and may not actually represent the inner workings of the JVM.
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

I'm going to withdraw the previous wild speculation. I tried reproducing the symptoms you have and my code works flawlessly. Let's see your code.
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
That makes sense. Ive taken out the Bufferedinputstream but am getting the same error. I looked at what you said about the clietn sending the closed flag while server is waiting for the next buffer.

Taking out all the close statements sends the entire image. So Ill try some guard to stop the program hanging because of the lack of close statements.

Cheers
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

I think you are closing in the wrong place. Like I said, I coded up the same task and it works fine. Let's see that code.
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
Here you go. This is the bit on the client that sends the image. I have the close statements commented out.



I also tried to take the close statements out and call them in another method, but to no avail. Same connection rest error.
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

This code worked fine for me:


Let's see that server.
Dan Lynch
Ranch Hand

Joined: May 16, 2003
Posts: 47
I was gonna say..."I bet this will be something simple that ive missed!!". And it is. I had a PrintWriter in the server side just to send an initial "Hi". I took it out, and it worked! Sorry for all this!
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

That's why I kept asking for the code. It's always better to get more eyes looking for the problem. Glad you got it fixed.
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
 
subject: Image transfer through sockets