Java Forum / General / December 2005
Network file transfer
Phillip D Ferguson - 23 Nov 2005 17:07 GMT Hello,
i am relatively new to java, but i have a large amount of experience in C++ so the transition hasn't been too bad. I am currently trying to build an application bit by bit so i am learning as much as i can. In the end i want an application that transfers XML files (via and HTTP which will be good for debugging), but for the moment i am trying to build one that just sends any file.
I have set up the appropriate code on each machine, sending a file from a client to a server. However i am having problems with sockets. I can send the file successfully but i would like the server to return some acknowledgement, then i can figure out how to send another file etc. I have tried sending a string but it doesn't work... can someone help? Eventually i would like to send multiple files sequentially so i do need some sort of acknowledgement even thought i am using tcp. Im also having trouble with the naming of a file. If i send a file from the client and want to save the file anywhere on the server, i need the file name from the client. Can i extract it from the input stream or do i need to request it separately?
My code for both sections is below:
Client code ------------------------------------------------------------------------------------------------------- import java.io.*; import java.net.*;
public class TCPClientfile {
public static void main(String[] args) throws Exception {
Socket clientSocket = new Socket(host address and port);
OutputStream dataOutput = clientSocket.getOutputStream(); File inputFile = new File("readme_eclipse.html"); // example file to send FileInputStream in = new FileInputStream(inputFile);
byte[] buffer = new byte[2048]; int numread;
while ((numread = in.read(buffer))>=0) { dataOutput.write(buffer,0,numread); System.out.println("sending..." +numread); // console confirmation of transfer } // if i de-comment the next section things dont work
/* BufferedReader inFromServer =new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
modifiedSentence = inFromServer.readLine();
System.out.println("FROM SERVER: " + modifiedSentence); */ inFromServer.close(); in.close(); dataOutput.close(); clientSocket.close(); } } -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Server code
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
import java.io.*; import java.net.*; public class TCPServerfile {
public static void main(String[] args) throws Exception {
ServerSocket welcomeSocket = new ServerSocket(port number); System.out.println("listening");
Socket connectionSocket = welcomeSocket.accept(); System.out.println("socket accepted"); InputStream dataInput = connectionSocket.getInputStream();
File outputfile = new File ("readme_eclipse2.html"); // renamed file from client, but how to get the original name? FileOutputStream out = new FileOutputStream(outputfile);
byte[] buffer = new byte[2048]; int numbread;
while((numbread = dataInput.read(buffer))>=0) { out.write(buffer, 0, numbread); System.out.println("Receiving..." + numbread); } // code will hang here if i try to send string as commented below
/* DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
outToClient.writeBytes(Response); System.out.println(Response); */ outToClient.close(); out.close(); dataInput.close(); connectionSocket.close(); welcomeSocket.close();
} } -------------------------------------------------------------------------------------------------------------------------------------
Can anyone offer me any corrections, advice.... good texts to read that would help me at all?
Cheers!!
Phillip Ferguson
MEng student strathclyde university
Roedy Green - 23 Nov 2005 17:29 GMT On Wed, 23 Nov 2005 17:07:15 GMT, "Phillip D Ferguson" <fergy27@ntlworld.com> wrote, quoted or indirectly quoted someone who said :
>I have set up the appropriate code on each machine, sending a file from a >client to a server. However i am having problems with sockets. All do you do is send a string of bytes, then, the receiver on getting them all and saving them safely away, can write single byte back into the stream 0 or 1. The other end on finishing the send, does a read and waits for the byte to arrive, and when it does closes the socket.
You don't even need multiple threads.
http://mindprod.com/applets/fileio.html for sample code.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Phillip D Ferguson - 23 Nov 2005 18:06 GMT I was just testing both sides on two machines. I have not used any multi-threading (yet). My complication was dealing with the current stream which has just sent a file, and configure it to send the acknowledgment. Do i need a new stream/socket?
What you are saying is after i have received my file, i close that socket, then open another to send a string to say the file has been received?
Is this correct?
thanks
Phillip
> On Wed, 23 Nov 2005 17:07:15 GMT, "Phillip D Ferguson" > <fergy27@ntlworld.com> wrote, quoted or indirectly quoted someone who [quoted text clipped - 12 lines] > http://mindprod.com/applets/fileio.html > for sample code. Roedy Green - 23 Nov 2005 21:30 GMT On Wed, 23 Nov 2005 18:06:45 GMT, "Phillip D Ferguson" <fergy27@ntlworld.com> wrote, quoted or indirectly quoted someone who said :
>Do i need a new stream/socket? A socket comes with two streams one for input and one for output.
Again, please see http://mindprod.com/applets/fileio.html for sample code.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
iksrazal@gmail.com - 23 Nov 2005 18:05 GMT > Hello, > [quoted text clipped - 5 lines] > which will be good for debugging), but for the moment i am trying to build > one that just sends any file. One simple and popular way to do this is via a class called HTTPClient from jakarta commons, and any servlet. Just recieve the xml file as a String. I can give more details if you'd like, or just use google.
HTH, iksrazal http://www.braziloutsource.com/
adamspe@gmail.com - 23 Nov 2005 20:07 GMT Unless you really want to roll your own server and if you want to do it via HTTP in the end then why not simply go that route (maybe write a simple servlet that consumes the XML on the server).
The client could do something very simple like:
import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.URL import java.net.HttpURLConnection;
... File xmlToSend = new File ( "/path/to/my.xml" ); if ( !xmlToSend.exists () ) ; // error URL u = new URL ( "http://host/App/servlet/Consumer" ); // or whatever HttpURLConnection connection = (HttpURLConnection)u.openConnection(); // need credentials or something? // connection.setRequestProperty ( "Authorization", "Basic ...." ); connection.setRequestMethod ( "POST" ); connection.setDoOutput ( true ); connection.setRequestProperty ( "Content-Type", "text/xml" ); connection.setRequestProperty ( "Content-Length", ""+xmlToSend.length() ): connection.setRequestProperty ( "Content-Disposition", "attachment; filename=\"" + xmlToSend.getName() + "\"" ); // possibly not the most efficient way to stream, maybe use java.nio InputStream in = new FileInputStream ( xmlToSend ); OutputStream out = connection.getOutputStream(); byte [] buf = new byte[4048]; int rd; while ( (rd = in.read(buf)) != -1 ) out.write ( buf, 0, rd ); in.close(); out.close(); if ( connection.getResponseCode() != 200 ) ; // something went wrong.
zero - 23 Nov 2005 20:37 GMT > Hello, > [quoted text clipped - 19 lines] > > My code for both sections is below: <snip>
I'm not sure what the "Response" is in your code, or why you're using a DataOutputStream. Have you tried something like this:
OutputStream out = connection.getOutputStream();
String data = "SERVER>>>FILE OK";
out.write(data.getBytes(), 0, data.length()); out.flush();
Phillip D Ferguson - 23 Nov 2005 22:58 GMT Cheers for all the input guys its very much appreciated!!!
The utility Roedy mentions is all good, but its doesn't answer my query. Can i leave the current socket open to send a string back to the client? Zero might have the answer with the code below.... i'll be back with the answer in 5 min.
Adam / iksrazal,
as much as i would love to just begin writing my own Http server but i just don't have the knowledge at this time. The spec at the moment is to send xml files from a (mobile) client, which is full of data samples. The server then confirms it has the file, then acts as a proxy to shunt the xml files to further client machines which will display the data samples. In the end i will want to write what you suggest but i feel i don't have the knowledge or the resources to do it. Do you have any recommendations on going down that road? At the moment i need to learn more than anything, so just writing a client/server setup which sends files is great. I then intend to go into XML and the proxy setup on the other side.
thanks again!
Phill
>> Hello, >> [quoted text clipped - 31 lines] > out.write(data.getBytes(), 0, data.length()); > out.flush(); Roedy Green - 23 Nov 2005 23:21 GMT On Wed, 23 Nov 2005 22:58:17 GMT, "Phillip D Ferguson" <fergy27@ntlworld.com> wrote, quoted or indirectly quoted someone who said :
>The utility Roedy mentions is all good, but its doesn't answer my query. Can >i leave the current socket open to send a string back to the client? >Zero might have the answer with the code below.... i'll be back with the >answer in 5 min. you simply open both the OutputStream and InputStream on the same socket.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
frankgerlach@gmail.com - 23 Nov 2005 23:23 GMT You should design a formal protocol (or a "language") for you client-server communications. From your code I am missing a length parameter, which must be sent BEFORE the file. Only then the server can determine whether everything has been read and can then send the acknowledgment to the client. The protocol should be like this: Client to Server: <SIZE><FILECONTENTS> Server to Client: <ACKNOWLEDGE> As soon as you application grows more complex, you will be better off with a well-defined protocol. Also, do not forget to flush() your output streams as soon as you expect the other side to sent some data. Your server code seems to read() infinitely, because you do not check whether you have read SIZE bytes.
Phillip D Ferguson - 24 Nov 2005 00:03 GMT From earlier for zero... response was a string that was sent to the client to confirm the server has received the file.
The server code reads until and end of file is found when the dataInput.read returns a -1. Then i know i have finished reading the file.
The problem is that after the while loop on the server terminates i cannot add any code that allows me to send via the same socket connection, or else it hangs. Otherwise the code exits nicely enough. now the server reads: ------------------------------------------------------- public static void main(String[] args) throws Exception {
ServerSocket welcomeSocket = new ServerSocket(6789); System.out.println("listening");
Socket connectionSocket = welcomeSocket.accept(); System.out.println("socket accepted"); InputStream dataInput = connectionSocket.getInputStream();
File outputfile = new File ("readme_eclipse2.html"); FileOutputStream out = new FileOutputStream(outputfile);
byte[] buffer = new byte[2048]; int numbread;
while((numbread = dataInput.read(buffer))>=0) { out.write(buffer, 0, numbread); System.out.println("Receiving..." + numbread); } System.out.println(numbread); System.out.println("whileloop completed");
out.close();
OutputStream outToClient = connectionSocket.getOutputStream();
String Response = outputfile.getName() + " has been received";
outToClient.write(Response.getBytes(),0,Response.length());
outToClient.flush();
connectionSocket.close(); welcomeSocket.close();
} -------------------------------------------------------
and the client ------------------------------------------------- public static void main(String[] args) throws Exception { String modifiedSentence;
Socket clientSocket = new Socket(host and port);
OutputStream dataOutput = clientSocket.getOutputStream(); File inputFile = new File("readme_eclipse.html"); FileInputStream in = new FileInputStream(inputFile);
byte[] buffer = new byte[2048]; int numread;
while ((numread = in.read(buffer))>=0) { dataOutput.write(buffer,0,numread); System.out.println("sending..." +numread); // this lets me know when everything is done }
dataOutput.flush();
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
modifiedSentence = inFromServer.readLine();
System.out.println("FROM SERVER: " + modifiedSentence);
clientSocket.close(); }
-----------------------------------------------------------------------------------------
i'm really tearing my hair out on this one..... and i know its done to practise... :-(
thanks for the input Phill
> You should design a formal protocol (or a "language") for you > client-server communications. From your code I am missing a length [quoted text clipped - 12 lines] > read() infinitely, because you do not check whether you have read SIZE > bytes. frankgerlach@gmail.com - 24 Nov 2005 09:46 GMT See my comments in your code :
public static void main(String[] args) throws Exception {
ServerSocket welcomeSocket = new ServerSocket(6789); System.out.println("listening");
Socket connectionSocket = welcomeSocket.accept(); System.out.println("socket accepted"); InputStream dataInput = connectionSocket.getInputStream();
File outputfile = new File ("readme_eclipse2.html"); FileOutputStream out = new FileOutputStream(outputfile);
byte[] buffer = new byte[2048]; int numbread; //at this point you MUST transmit/read the length of the file //because you MUST terminate your loop after the file has been //completely read. Currently this is an ENDLESS loop !! while((numbread = dataInput.read(buffer))>=0) { out.write(buffer, 0, numbread); System.out.println("Receiving..." + numbread); } //Your loop should look like this: // int fileSize=<READ FILE SIZE FROM INPUTSREAM> // int readUpToNow=0; // do{ // int validBytes=dataInput.read(buffer,0,buffer.length); // out.write(buffer, 0, validBytes); // readUpToNow+=validBytes; // }while(readUpToNow<fileSize);
System.out.println(numbread); System.out.println("whileloop completed");
out.close();
OutputStream outToClient = connectionSocket.getOutputStream();
String Response = outputfile.getName() + " has been received";
outToClient.write(Response.getBytes(),0,Response.length());
outToClient.flush();
connectionSocket.close(); welcomeSocket.close();
}
adamspe@gmail.com - 29 Nov 2005 16:23 GMT My thought here was not that you write an HTTP Server. There's no need to do such a thing since there are many freely available ones out there to meet that need. you could simply run Tomcat with HTTP enabled or Apache+tomcat or pick your favorite webserver servlet engine combo and write a tiny servlet to plug in there to consume your XML. All the protocol details, authentication, etc. will be handled by the server and the java.net classes on your client side, no need to -really- understand all the specifics of the underlying protocol, just small bits of code on both sides of the wire.
Thomas G. Marshall - 29 Nov 2005 20:03 GMT adamspe@gmail.com said something like:
> My thought here was not that you write an HTTP Server. There's no > need to do such a thing since there are many freely available ones [quoted text clipped - 5 lines] > no need to -really- understand all the specifics of the underlying > protocol, just small bits of code on both sides of the wire. Please supply a quote.
adamspe@gmail.com - 30 Nov 2005 16:44 GMT Sorry.
>> Adam / iksrazal, >> [quoted text clipped - 20 lines] > understand all the specifics of the underlying protocol, just small > bits of code on both sides of the wire. My point was that existing software and APIs exist to deal with both sides of the wire via HTTP that could be re-used without the need to invent a protocol and write the client and server.
Phillip D Ferguson - 01 Dec 2005 21:44 GMT Adam,
your comments are much appreciated!!! I began to realise that this is the easiest approach, as i really wish i had the time to go into java in that much details as to code my own http server, but you are not the only one to suggest that i use tomcat etc to do this. How simple is it to write myself a servlet to deal with my xml files? I have yet to go into XML in detail with the DOM and SAX availabilities.
Cheers
Phill
> Sorry. > [quoted text clipped - 32 lines] > sides of the wire via HTTP that could be re-used without the need to > invent a protocol and write the client and server.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|