Win a copy of Cross-Platform Desktop Applications: Using Node, Electron, and NW.js this week in the JavaScript forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

sending a file to a client over a server  RSS feed

 
luc comeau
Ranch Hand
Posts: 97
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi everyone,
In this context, i have an xml file that is on the server side(by the way right now i dont have this written),the file needs to be sent over the server to the client.
On the client side i have already programed an interface that reads an interperates the xml file and displays its contents to the user.But the problem is i have the file name hardcoded into my app, but now its time to get that file from a server that i must make up.
My question is this,What input and output streams should i use when constructing my client and server input and output streams.It sounds easy enought but im new at this server stuff, all i want to do is just get the file sent to the client, then i already have the code to process the file.
Any suggestions would be terrific, thanks
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you're writing your own server, you'll likely be using sockets. The Sun tutorial is a pretty good starting point.

In short, the server listens for requests from clients. When a request comes in the server obtains a new Socket object, reads the request from the socket and writes the response to the socket. Servers with more than a couple clients usually run this process on a new thread or a thread from a pool, but you can get started without adding threads to the mix just to make it easier to learn.

Try the examples in the tutorial, start coding up your own ideas and let us see what you come up with!
 
luc comeau
Ranch Hand
Posts: 97
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi SJ,
Thanks for the input, iv read the sun tutorial several times and actualy writen some very basic client servers that communicate back and fourth, but only by sending text.I cant find anywhere on how, say on the servers end, say they hypothetically have this xml file stored that contains information on a certain user.Upon the user being authenticated by a username and password the xml file will be sent to the client.
This is where i run into the problem, i can only find examples that the client recieves text and sends text.I dont even know if its possible to send an entire file to a client.
Have you any idea if this is possible, if so maybe you can direct me to a place where i can learn how to do this.
As i have done some more research on the matter looking at the java.io package i havnt seen anything in there that allows an entire file to be sent it seems that only arrays of chars or bytes can be sent.Wich might mean that what i am trying to do is not even possible.It just sounded so easy i assumed there would be a simple way to do it.Also the more i think about it, it sounds like i should be using some type of FTP server or something, but i dont want the user to have to do anything but enter a user name and password then the logic behind my interface will get the file on its own and interpret it.As you can probably see i'm lost, but i need a solution to this problem.Anyways if you can get back to me it would be awesome.thanks
 
Clivant Yeo
Ranch Hand
Posts: 124
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Layer the output and input streams as DataInputStream and DataOutputStream or any relevant byte-oriented streams.

Eg:

// accept a client's connection
Socket client = ss.accept();

// Layer the io streams of socket into byte-oriented ones
DataInputStream is = new DataInputStream(client.getInputStream());
DataOutputStream is = new DataOutputStream(client.getOutputStream());

// Use RandomAccessFile to read the file to be sent
// Send the pieces read by RandomAccessFile byte by byte out of is

Hope it helps

Regards,
Clivant
 
luc comeau
Ranch Hand
Posts: 97
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hey,

Again rethinking this for simplicity, i want the client side to just send a string to the server.I guess im geting confused because it seems thst u say the Servers input stream is:

"DataInputStream is= new DataInputStream(client.getInputStream());

doesnt this suggest that the servers input stream is going to be dependant on what the clients inputstream is? thats how im interpreting the client.getInputStream() part. But this means when i write the client side of this C/S pair im going to have to make its inputStream the same as the clients so that it can read in the text?When infact i want the server to be able to read in text, and the client to send the text,but i want the server to send this byte buffer over(my file)to the client, wich means the clients inputStream should be the same as the Servers outPutStream doesnt it?So this would contradict what you have writen about the the servers inputstream depending on the clients input stream, unless i have interpreted it all wrong.

So i guess what i need help on is determining exactly what the input and output streams are for each the client and the server side.

ie:Server inputStream----->then i need to know the type of inputStream the server needs to have in order to recieve text.
outputStream----->need to know what type of OutputStream the server needs to send this byte buffer(wich i think you said DataOutputStream)but with the correct parameters.

Client: inputStream---->What type of inputStream the client needs to recieve this byte buffer that the servr is sending it.

outPutStream---->What type of outPutStream the client needs to send just a text string over to the server.

If this last section could be answered it would be great ,againa thanks a bunch for everyones patience.
 
David Harkness
Ranch Hand
Posts: 1646
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by luc comeau:
doesnt this suggest that the servers input stream is going to be dependant on what the clients inputstream is?
Clivant's code runs on the server. Both the client and server each have their own sockets, and the sockets are connected to each other over the network. But note that their streams are "crossed": whatever the client writes to its socket's output stream shows up on the server's socket's input stream and vice versa.

The streams you use do not have to match in any way, but you'll find it easier to use the same types on both ends. Once it hits the sockets and goes over the network, it's all just bits on the wire.

But the choice of stream depends on the protocol you are going to design for communicating. Even though your needs are simple, you still have to specify exactly the "language" the client and server will use to talk to each other. It could be as simple as the following.No error-handling and only limited parsing on the server side are needed for this. If the client needs to specify the file name or the server will send an error code for bad passwords, it gets more complicated. For the above protocol you could easily get away with using the bare Input/OutputStreams from the Socket class.

I recommend you take a look at the JavaDocs for the various stream classes. DataOutputStream is useful for sending Java primitive values like ints, longs, and doubles. Since it extends OutputStream, you can also use it to send byte arrays. If you need to send anything after the XML file, however, you'll need to first send the total length of the byte array followed by the byte array itself. This allows the client to know how much to read for the XML before switching to the next expected piece.

Hopefully I haven't complicated things too much. Unfortunately, the answer is that there is no "right" stream to use. Again for the above protocol, I'd probably use a Writer/Reader pair for the client-to-server path since it's line-oriented and a DataOutput/InputStream for the other direction to send the XML file (it has a handy readFully method).

Once you get that working, if performance is an issue you can swap in the buffered versions of those, but only do this once you have it working without buffering.

[ Typos ]
[ January 26, 2005: Message edited by: David Harkness ]
 
luc comeau
Ranch Hand
Posts: 97
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi,

Again thanks for the post.It was useful.I actualy just finshed coding my client and server pair.Im actualy geting this error when the client side is run:


This is when i had already started my server and waited a bout 10 seconds before i started my client, once i started the client thats the error i get.It seems to not even be geting into my main method.
This main method i am about to show is in a GUI class.



Mind you the GUI worked fine before i just added the code in bold.
This is OneConnection class that is used in my server class.




And last of all the server class



All clases ARE in the same folder, im just not familiar with the error im getting.I tried runing the client on its own..without starting the server and it fails as its suposed by getting the IOException error.So im not sure whats going on when i run the server and why its not connecting.
I hope the code helps u better understand what i was trying to do!

Again any hints would be great .Specially geting rid of that stupid error...because after that i think its justscrewing around to figure out how to read that file.
-luc
 
luc comeau
Ranch Hand
Posts: 97
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi again,
Stupid emacs editor.I have to open a shell for it to work.But im still having a problem when my code goes to the getRequest() method.The actual point where my program stops i have pin pointed to be the readLine(). wich i assume is because im not using my streams in the right way.Any ideas, im going to work on it , but if anyone sees anything quick shout here.thanks
-luc
 
luc comeau
Ranch Hand
Posts: 97
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
one problem fixed, forgot to add auto flushing true on my PrintWriter.
it now looks like this



It seems to get the filename just fine now, but when it trys to do the readFully(fromServer) on the client side, there is an exception thrown and the program exits.

The exception is an EOFException.looks like this:


And im confused here because i checked the length of the file before i did the read fully and it says its 220, i looked at the xml file i am using and its roughly 212 characters i dont know exacly if this number of bytes seems correct given the number of characters, im not sure how that works.

Also in the sendFileBack method it gets through the entire method including the out.write(buff) because i put print statments after that and they still printed.

So i guess my problem is when the client side trys to do the readFully(fromServer), its some how getting an EOFException and i have no idea why thats popping up given that it clearly wrote the file on the server side.This is where i start to sketch out on details.As you may have noticed i made my byte[] array on the client side size 10000, just because i wasnt sure how mnany bytes my file would be, i hope this doesnt matter?Anyways thats enough for now i've already writen to much im sure.Any sugestions anyone.?
 
luc comeau
Ranch Hand
Posts: 97
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
yes yet another consecutive post ..sorry
The darn byte buffer on the client size has to be the EXACT same as on the server sidewich i think is rediculous becuase how is the client suposed to know the size of the file before they recieve it

Anyways i know have the file ebing sent by the server to the client, expect for now i run into the damm problem of somehow using this byte array to build a file on the client side.i knew i was going to run into this problem, that why i wish i could just get the file sent to me as a WHOLE file not these damm bits, its wasting so much memroy and stuff doing all these conversions to bytes etc.

But i have a feeling its my only option at the moment.Wich now leads me to ask if anyone knows how to create a file from a byte[] buffer.I have looked extensivly in other forums and google etc and cant find anything.If requested to i will start a new thread on this topic alone, but would like to keep this one open on the premis that maybe someone can help me figure out how to avoid having to do this "converting a byte array to a file" operation.!!!

On that note my head hurts im geting some advil

Any coments plz leave em..i wont be posting again i promise!!lol
 
David Harkness
Ranch Hand
Posts: 1646
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Good job, Luc! You did some good detective work to figure out all of those problems and nailed every one.

Regarding the sizing of the byte[] to receive the file on the client side and the EOFException, you are correct. The readFully() method tries to fill the buffer you give it. That's why you had to size it using the length of the file on the server side. Well, you can do that on the client side as well by having the server first send the length of the file.And on the client side you'd read it before creating the byte[].Now you just need to write that buffer to a file. This is actually very similar to how you sent it from the server. You create a File, get its OutputStream, write(fromServer) the buffer to it, and finally close it.
 
luc comeau
Ranch Hand
Posts: 97
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hey David,
Thanks for the tip i was thinking of doing something exactly like u just wrote down for me, but i didnt know about that readInt() method,infact the way you have it doesnt work because when i do the write(len) in the sendFileBack() method, its giving me a huge negative number,this was a simple fix, instead of write(len), i just changed it to writeInt(len) lol, simple but honest mistake.

Im going to try to get that byte buffer into a file today thats my goal, i infact have to cater to the Member of Parlament today so i dont know how much work im going to be getting done.Should be intresting seing Minister Mereson, Andy Scott, Andy Reddick and all them politician guys :roll: .

I'll let you know how the file making goes, thanks again.
-luc
 
luc comeau
Ranch Hand
Posts: 97
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok, so this is my current problem,

I am using the SAXBuilder class to build and parse my xml document.My thing is that i want to build the Document from the byte array i read in from the server,maybe i dont want to write it to a file,because i dont nessesarily want the file to be writen to the users harddrive.I just thought i could turn the byte array into a file, then return that file to be used in the SAXBuilder.build(File fName) method.But i think this constructor looks for a file in a directory not a file..that i owuld have made and not wrote to a directory.

So i guess my thing is now, trying to use one of the other constructors to build(wich btw is here if you would like to lookSaxBuilder class)

I was thinking, and i saw one that takes in a input stream, maybe instead of wrtiing my byte buffer to a file i could just perhaps return the stream and use that streeam to do a build on my documnet?This is all up in the air.

But as for being able to write it to a file, like i orignally wanted to, i had to use RandomAccessFile like i was sugested to in the first post.Wich worked perfect, except for the fact that i need a File not a RandomAccessFile for my builder constructor .

Any bright ideas on how i should go about doing this?
-luc
 
luc comeau
Ranch Hand
Posts: 97
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
yet another consecutive post...sorry

So i figured out a way to get it to work.All i had to do was add like two lines of code.



mind you i put this in the client side of the code right after i closed the stream etc.
So what this does, which is not exactly desired is writes a file to the clients harddrive, but what i wanted to do was delet it right after i was done using it, so i tryed that by using the File.delete() method .and it doesnt do it, im not sure if it has anything to do with privledges or what not?But its not a huge deal seing as how this is only a prototype.
If you have any suggestions on why its not deleting the file that would be awesome!

-luc
 
David Harkness
Ranch Hand
Posts: 1646
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by luc comeau:
lol, simple but honest mistake.
I was trying to trick you but you foiled my plan again! Actually, I should point out that I've never used DataInput/OutputStream -- I was just going from the JavaDocs. Ah, I see why it failed. write(int b) treats the int as a byte and just writes the low 8 bits, so when you called readInt() on the other side, it used the 8 bits of the int written plus the first 24 bits of the file. In any case, good catch.
I was thinking, and i saw one that takes in a input stream, maybe instead of wrtiing my byte buffer to a file i could just perhaps return the stream and use that streeam to do a build on my documnet?
That would work just fine in your case. You have another option as well which would be required if you needed to have the server send something after the XML file. Since you don't, you should be able to skip reading into the byte[] (and skip sending/reading the length, though it doesn't hurt), and simply hand the InputStream off to the SAXBuilder.

However, the other option is to use one of the other handy IntputStream classes: ByteArrayInputStream. It simply wraps an existing byte array and uses it to feed whoever calls read() -- just as if the bytes were coming from a file or socket.
i had to use RandomAccessFile
It's not a problem to use it, obviously, but I don't see why it would be necessary. Just out of curiosity, can you elaborate on the problem you had using File?

What is the exception you get when deleting the File? Perhaps the SAXBuilder still has the File open for reading, but that's just a total guess.
[ January 27, 2005: Message edited by: David Harkness ]
 
luc comeau
Ranch Hand
Posts: 97
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hey again,

Just out of curiosity, can you elaborate on the problem you had using File?


Well as you know i had an array of bytes to use to build a new file from, but if you look at all of the methods for File class there is one to
write (byte[]),So i figured i would look at the FileWriter Class, wich also didnt have a write(byte[]) method only ones that can write a char[], a char, and a string.

So this is why i was forced into the randomAccessFile class because it has a write(byte[]) method right int he class itself.But yes that was the problem, but again i "solved" it by just making another File using the name from the RandomAccessFile, so basically its just a copy of the RandomAccessFile.

What is the exception you get when deleting the File? Perhaps the SAXBuilder still has the File open for reading, but that's just a total guess.


I think that may be part of the reason i can't delete it, but im not really sure.It's not throwing an exception.And about having the file open for reading...well the file the SAXBuilder is reading from is a File not a RandomAccessFile, so i don't think i can actually say file.close() or what not, i tryed that actually.And i believe that to close it needs to be a FileReader wich im not explicitly making, i figure the SAXBuilder.build method does that all for me when i hand it the name of the file , just a guess though.

So bascially its just not removing it from the folder i wrote it to, and not throwing an exception, like i really have no idea,i would think that it would be throwing an exception if it couldnt' delete it, or if it didn't have access to delete it

I think next week im going to try handing the build method the stream instead of a file, i just dont have time to tackle that today going to nova scotia in 3 hours.

Anyways if you gained anything from what i said post back and tell me if u got any ideas, thanks again for the suggestions and everything vvery helpful indeed.

-luc
 
luc comeau
Ranch Hand
Posts: 97
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
well this didnt obviosuly make any sense
Well as you know i had an array of bytes to use to build a new file from, but if you look at all of the methods for File class there is one to
write (byte[]),


its suposed to say "...for the File class there IS NOT one to...."

my bad
 
David Harkness
Ranch Hand
Posts: 1646
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by luc comeau:
well this didnt obviosuly make any sense ... its suposed to say "...for the File class there IS NOT one to...."
LOL, ya I had to read it twice, but I got it.
but if you look at all of the methods for File class there is [not] one to write (byte[])
FileOutputStream is what you wanted.It's just a matter of getting familiar with the various classes in the java.io package. There are quite a few, and they've evolved with each JDK (1.4 introduced an entirely new way of deaiing with I/O called New I/O that uses Buffers and Channels), so it's not an easy task. You might want to go through the Sun tutorial as I believe it covers the differences between streams and readers/writers. It should also cover the buffered versions of each.

RandomAccessFile is basically a combination of a File, DataInput- and DataOutputStream. AFAIK, it cannot be used with readers/writers since it only implements DataInput/Output and not their respective Stream implementations. It's extremely useful for dealing with files that are composed of fixed-length records, however.
It's not throwing an exception.
I forgot that File.delete() returns false when it cannot delete it rather than throwing an IOException telling you why it couldn't be deleted. Since SAX is a callback-oriented API -- it doesn't build an entire Document at once but rather calls your callback methods as pieces are read from the stream -- I figured it may still leave the File and its InputStream open. However, given that build() returns a Document, I'm guessing SAXBuilder uses SAX to read in and build the entire Document. If that's the case, it should close the file before returning.

So you create a RandomAccessFile to write the XML, then create a File using the same name and pass it off to SAXBuilder. Then you try to delete the file through the File you created. Are you closing the RandomAccessFile after writing it and before calling SAXBuilder.build()? If not, then it still has it opened. The RAF and File you created both point to the same file on disk, and thus you cannot delete the File while the RAF is still open.

If that's not the problem, it will take more digging.
going to nova scotia in 3 hours.
Wow, enjoy your vacation (?) and take some pics!
 
luc comeau
Ranch Hand
Posts: 97
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hey david,

Once again you're on the ball, i didn't close the random access file after i finished the method that i created in it .haha easy fix none the less, took me less than two seconds this morning, im quite frigin tired though, intense weekend of partying in halifax, i love how the bars are open till four am and the casino is open all night.Fun but im pretty sure i couldnt live liek that every weekend, im dead tired!

Also got lost on a stupid transit bus till midnight in dartmouth, that was one effin intense adventure haha.Pictures were taken, and i must admit the population concentration of beautiful women there is rediculous, ive never seen so man hot girls at one bar in my entire life , if your ever in halifax i strongly reccomend you go to "the palace".

This week, i got some more IO stuff to do and some GUI things as well.Im sure if i have any questions ill be posting again, depending on its relevance to this thread i might post in here or start a new one, so be looking hahah.
Thanks again for all your help!

cheers,
-luc
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!