I try to create the simplest Simplest WebServer and Client using HTTP. 开发者_如何转开发(Please, don't tell me to using Apache HTTPClient).
Client: try to PUT some file to Server.
// **PUT**
if(REQUEST.toUpperCase().equals("PUT")) {
File sourceFile = new File(fileName);
if(!sourceFile.canRead()) {
System.out.println("Have not access to this file...");
return;
}
try {
BufferedInputStream is = new BufferedInputStream(new FileInputStream(sourceFile));
URL url = new URL("http://" + HOST+":"+PORT);
System.setProperty("http.keepAlive", "true");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestMethod("PUT");
connection.setRequestProperty("Content-Type", "Application/octet-stream");
connection.setRequestProperty("Content-Length",Long.toString(sourceFile.length()));
connection.addRequestProperty("Content-disposition","attachment; filename="+fileName);
BufferedOutputStream os = new BufferedOutputStream(connection.getOutputStream());
byte[] buf = new byte[sizeArr];
int r = 1;
while((r = is.read(buf)) > 0) {
os.write(buf, 0, r);
}
os.flush();
os.close();
System.out.println("Waiting for the response...");//this is written to console
System.out.println(connection.getResponseCode());//HERE infinite waiting
is.close();
} catch (MalformedURLException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
On Server: if Request == PUT
, then:
// **PUT**
if (header.toUpperCase().equals("PUT")) {
System.setProperty("http.keepAlive", "true");
String fileName = null;
if((fileName = extract(request.toUpperCase(),"FILENAME=","\n")) == null) {
fileName = "UnknownFile.out";
}
try {
File sourceFile = new File(fileName);
BufferedOutputStream osFile = new BufferedOutputStream
(new FileOutputStream(sourceFile));
byte[] locbuf = new byte[sizeArr];
int locr = 1;
while((locr = is.read(locbuf)) > 0) {
System.out.println("locr= "+locr);//this is written to console
osFile.write(locbuf, 0, locr);
}
System.out.println("Ending to record the data to the file.");
// this is NOT written to console
osFile.flush();
osFile.close();
}
catch(IOException ex) {
os.write(CodeRequest("500 Internal Server Error").getBytes());
os.close();
ex.printStackTrace();
return;
}
System.out.println("Trying to send 200 OK");
os.write(CodeRequest("200 OK").getBytes());
os.flush();
os.close(); // where os = clientSocket.getOutputStream();
}
Why doesn't the Client get a Response from the Server? If I interrupted the Client's infinite loop, then WebServer would correctly record data to file. But Client will never know that his file was normally uploaded to the server. If I comment out this statement on Client:
// System.out.println(connection.getResponseCode());
Then Client correctly exit from loop and ends. But Server doesn't even write to console this:
while((locr = is.read(locbuf)) > 0) {
System.out.println("locr= "+locr);//this is NOT written to console
osFile.write(locbuf, 0, locr);
}
Server ONLY writes this to console this:
localExcString index out of range: -1
without any Error message.
What's wrong?
Your example code for the server doesn't show the declaration and initialisation of 'is'. However, my guess is that since the session is keep alive the call to is.read() will block until some data arrives. You have set the content length in the client, so I would be expecting to see the read loop complete when that amount of data has been successfully read.
What string is the CodeRequest
method returning in the server code? I think that the problem may be that you are not putting a CRLF at the end of the status line and another one at the end of the response header. For details, read the HTTP 1.1 specification.
You need to call URLConnection#getInputStream()
after the write to actually send the request (and thus retrieve the response). Only after this point you can request the response status. This is implemented so because it might take longer to build the request body than to actually sending it and also because there's actually no point of having a request if you're not interested in the response.
Edit sorry, I was wrong. The getResponseCode()
already implicitly calls getInputStream()
.
Anyway, I created a small testcase (see SSCCE for more info) and it just works fine. Try it and see if it works in your case as well.
Client:
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class Test {
public static void main(String[] args) throws Exception {
String data = "Hello!";
URL url = new URL("http://localhost:8080/playground/test");
OutputStream output = null;
try {
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("PUT");
output = connection.getOutputStream();
output.write(data.getBytes());
System.out.println("Response code: " + connection.getResponseCode());
} finally {
if (output != null) try { output.close(); } catch (IOException ignore) {}
}
}
}
Server:
package mypackage;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Test extends HttpServlet {
protected void doPut(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
InputStream input = null;
try {
input = request.getInputStream();
int data;
while ((data = input.read()) > -1) {
System.out.write(data);
}
System.out.println();
} finally {
if (input != null) try { input.close(); } catch (IOException ignore) {}
}
}
}
Result should be a Response code: 200
in the client's stdout and a Hello!
in the server's stdout.
Hope this helps in pinpointing the cause of your problem.
On Server:
String strFileLen = extract(request.toUpperCase().trim(),"CONTENT-LENGTH:","\n");
long fileLength = 0;
if(strFileLen != null) {
fileLength = Long.parseLong(strFileLen.trim());
System.out.println("fileLength= "+fileLength);
};
byte[] locbuf = new byte[sizeArr];
int locr = 1;long sumLen = 0;
if(fileLength != 0) {
while((sumLen += (locr=is.read(locbuf))) != fileLength) {
System.out.println("sumLen= "+sumLen);
osFile.write(locbuf, 0, locr);
}
}
=================================================== This works well.
精彩评论