写了一个MyServer模拟http server 接收post请求。
java代码:package socket;import java.io.*;
import java.net.*;public class MyServer {
public static void main(String args[]) throws Exception{
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("server is ok.");
while(true){
Socket socket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = in.readLine();
while(line!=null){
System.out.println("Client: " + line);
line = in.readLine();
}
System.out.println("current user close the session.");
in.close();
socket.close();
}
}
}
用浏览器打开下面的html文件,并提交数据:<head>
<title>test my server</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>upload</p>
<form name="UploadForm" method="post" action="http://localhost:8080/1.jsp">
<input type="text" name="myname" /><br>
<select name="myage">
<option value="18">18</option>
<option value="20">20</option>
<option value="22">22</option>
</select><br>
<input type="submit"value="Sutmit">
</form>
</body>
</html>MyServer打印出来的数据开始还正常:
server is ok.
Client: POST /testupload.jsp HTTP/1.1
Client: Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Client: Referer: http://localhost:8080/post.html
Client: Accept-Language: zh-cn
Client: User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)
Client: Content-Type: application/x-www-form-urlencoded
Client: Accept-Encoding: gzip, deflate
Client: Host: localhost:8080
Client: Content-Length: 28
Client: Connection: Keep-Alive
Client: Cache-Control: no-cache
Client:
走到这里的时候, 按http协议,接下来浏览器该传送post的数据了,但是程序走到这里就不走了。当我按esc之后,post数据才被提交上去
Client: myname=wwwwwwwwwwww&myage=18
current user close the session.很奇怪!
高手出来!
java代码:package socket;import java.io.*;
import java.net.*;public class MyServer {
public static void main(String args[]) throws Exception{
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("server is ok.");
while(true){
Socket socket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = in.readLine();
while(line!=null){
System.out.println("Client: " + line);
line = in.readLine();
}
System.out.println("current user close the session.");
in.close();
socket.close();
}
}
}
用浏览器打开下面的html文件,并提交数据:<head>
<title>test my server</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>upload</p>
<form name="UploadForm" method="post" action="http://localhost:8080/1.jsp">
<input type="text" name="myname" /><br>
<select name="myage">
<option value="18">18</option>
<option value="20">20</option>
<option value="22">22</option>
</select><br>
<input type="submit"value="Sutmit">
</form>
</body>
</html>MyServer打印出来的数据开始还正常:
server is ok.
Client: POST /testupload.jsp HTTP/1.1
Client: Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Client: Referer: http://localhost:8080/post.html
Client: Accept-Language: zh-cn
Client: User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)
Client: Content-Type: application/x-www-form-urlencoded
Client: Accept-Encoding: gzip, deflate
Client: Host: localhost:8080
Client: Content-Length: 28
Client: Connection: Keep-Alive
Client: Cache-Control: no-cache
Client:
走到这里的时候, 按http协议,接下来浏览器该传送post的数据了,但是程序走到这里就不走了。当我按esc之后,post数据才被提交上去
Client: myname=wwwwwwwwwwww&myage=18
current user close the session.很奇怪!
高手出来!
2、你在读到数据后,应该向客户端发出应答,否则客户端不会关闭Socket(除非超时,可能很长),这样你的程序还是会挂在那里不退出。
readline要到文本行结尾才返回,
但post提交的数据通过http消息体发送,末尾不必加换车符,
所以此时readline就卡在那里了。空行是http头和消息体的分隔,
可以在读到空行后,退出循环,转而用普通的读字符方式处理。
改成read(char[]), 但是问题还是没有消失,现在正在试验用2楼的方法!
对于原始数据的Socket发送,一定不要用readLine,否则以后会出现很多编码字符上的误解!
这是readLine()有缓冲。你直接使用字符流就行了。代码如下:Reader r=new InputStreamReader(socket.getInputStream());
int ch;
while((ch=r.read())!=-1){
System.out.print((char)ch);
}
System.out.println("current user close the session.");
r.close();
答:楼主只要客户端发的数据能够一下子全显示出来,而不是readLine()那样显示不全就停止在那儿。这与“流是不会结束的”是没有关系的。只要数据能够一下子全显示出来,楼主的目的就达到了。
关于流结束的问题,那是一个长连接,双方按HTTP协议来交互就行了[需要楼主解析HTTP头部内容],没有什么奥秘的。
我觉得浏览器提交数据的方式应该是可靠的巴。
import java.net.ServerSocket;
import java.net.Socket;public class MyHttpServer {
//服务器根目录。post.html, upload.html都放在这里面。
public static String WEB_ROOT = "c:/root";
private int port;
//请求的文件/url 路径
private String requestPath;
//处理multipart用的boundary
private String boundary = null;
//post提交方式的数据长度
private int contentLength = 0;
public MyHttpServer(String root, int port) {
WEB_ROOT = root;
this.port = port;
requestPath = null;
} private void doGet(Socket socket) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
if (new File(WEB_ROOT + this.requestPath).exists()) {
InputStream fileIn = new FileInputStream(WEB_ROOT
+ this.requestPath);
OutputStream out = socket.getOutputStream();
byte[] buf = new byte[fileIn.available()];
fileIn.read(buf);
out.write(buf);
out.close();
fileIn.close();
reader.close();
socket.close();
System.out.println("connection colsed");
}
} private void doPost(Socket socket, BufferedReader reader) throws Exception {
//下面行出问题了, 如果不使用前面new的reader,用下面方式新开的reader读不到数据。
//BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
if ("".equals(line)) {
break;
} else if (line.indexOf("Content-Length") != -1) {
this.contentLength = Integer.parseInt(line.substring(line.indexOf("Content-Length") + 16));
}
//表明要上传附件, 跳转到doMultiPart方法。
else if(line.indexOf("multipart/form-data")!= -1){
//得multiltipart的分隔符
this.boundary = line.substring(line.indexOf("boundary") + 9);
this.doMultiPart(socket, reader);
return;
}
}
//继续读取普通post(没有附件)提交的数据
System.out.println("begin read posted data......");
char[] buf = null;
if (this.contentLength != 0) {
buf = new char[this.contentLength];
reader.read(buf, 0, contentLength);
System.out.println("The data user posted: " + new String(buf));
}
String response = "";
response += "HTTP/1.1 200 OK\n";
response += "Server: Sunpache 1.0\n";
response += "Content-Type: text/html\n";
response += "Last-Modified: Mon, 11 Jan 1998 13:23:42 GMT\n";
response += "Accept-ranges: bytes";
response += "\n";
OutputStream out = socket.getOutputStream();
//PrintWriter writer = new PrintWriter(socket.getOutputStream());
//writer.write(response);
String body = "<html><head><title>test server</title></head><body><p>post ok:</p>" + (new String(buf).replaceAll("&", "<br>")) + "</body></html>";
System.out.println(body);
//writer.write(body);
//writer.flush();
out.write(response.getBytes());
out.write(body.getBytes());
out.flush();
reader.close();
socket.close();
} private void doMultiPart(Socket socket, BufferedReader reader) throws Exception {
System.out.println("doMultiPart ......");
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
if ("".equals(line)) {
break;
} else if (line.indexOf("Content-Length") != -1) {
this.contentLength = Integer.parseInt(line.substring(line.indexOf("Content-Length") + 16));
System.out.println("contentLength: " + this.contentLength);
} else if (line.indexOf("boundary") != -1) {
this.boundary = line.substring(line.indexOf("boundary") + 9);
System.out.println("********" + boundary);
}
}
System.out.println("begin get data......");
if (this.contentLength != 0) {
byte[] buf = new byte[this.contentLength];
int totalRead = 0;
int size = 0;
while (totalRead < this.contentLength) {
size = socket.getInputStream().read(buf, totalRead, this.contentLength - totalRead);
totalRead += size;
}
System.out.println("totalRead: " + totalRead);
String dataString = new String(buf, 0, totalRead);
System.out.println("data posted:\n" + dataString);
//得到附件的开始位置和结束位置
int pos = dataString.indexOf(boundary);
System.out.println("pos: " + pos);
pos = dataString.indexOf("\n", pos) + 1;
System.out.println("pos: " + pos);
pos = dataString.indexOf("\n", pos) + 1;
System.out.println("pos: " + pos);
pos = dataString.indexOf("\n", pos) + 1;
System.out.println("pos: " + pos);
pos = dataString.indexOf("\n", pos) + 1;
int start = dataString.substring(0, pos).getBytes().length;
pos = dataString.indexOf(boundary, pos) - 4;
System.out.println("pos: " + pos);
int end = dataString.substring(0, pos).getBytes().length;
//得到附件的文件名
int fileNameBegin = dataString.indexOf("filename");
System.out.println("fileNameBegin: " + fileNameBegin);
int fileNameEnd = dataString.indexOf("\n", fileNameBegin);
System.out.println("fileNameEnd:" + fileNameEnd);
String fileName = dataString.substring(fileNameBegin, fileNameEnd);
fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
fileName = fileName.substring(0, fileName.length()-2);
System.out.println("file Name------------>" + fileName);
OutputStream fileOut = new FileOutputStream("c:\\" + fileName);
fileOut.write(buf, start, end-start);
fileOut.close();
fileOut.close();
}
String response = "";
response += "HTTP/1.1 200 OK\n";
response += "Server: Sunpache 1.0\n";
response += "Content-Type: text/html\n";
response += "Last-Modified: Mon, 11 Jan 1998 13:23:42 GMT\n";
response += "Accept-ranges: bytes";
response += "\n";
// response.getBytes(charsetName);
OutputStream out = socket.getOutputStream();
out.write("<html><head><title>test server</title></head><body><p>Post is ok</p></body></html>".getBytes());
out.flush();
reader.close();
socket.close();
System.out.println("session closed.");
} public void service() throws Exception {
ServerSocket serverSocket = new ServerSocket(this.port);
System.out.println("server is ok.");
while (true) {
Socket socket = serverSocket.accept();
System.out.println("new request coming.");
BufferedReader reader = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
reader.(1024);
String line = reader.readLine();
String method = line.substring(0, 4).trim();
this.requestPath = line.split(" ")[1];
System.out.println(method);
if ("GET".equalsIgnoreCase(method)) {
System.out.println("do get......");
this.doGet(socket);
} else if ("POST".equalsIgnoreCase(method)) {
reader.reset();
reader = null;
System.out.println("do post......");
this.doPost(socket, reader);
}
}
} public static void main(String args[]) throws Exception {
MyHttpServer server = new MyHttpServer("c:/root", 8080);
server.service();
}
}post.html<html>
<head>
<title>test my server</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>upload</p>
<form name="UploadForm" method="post" action="testupload.jsp">
<input type="text" name="myname" /><br>
<select name="myage">
<option value="18">18</option>
<option value="20">20</option>
<option value="22">22</option>
</select><br>
<input type="submit"value="Sutmit">
</form>
</body>
</html>先不看有附件的情况,现在doGet方法可以work, doPost还有问题,我描述在方法里面。谢谢几位高手再看看。
1)说一句可能楼主生气的话:楼主对socket流的用法不是很规范。原因是:每一个socket,关联一个输入流及输出流,
当楼主转换成BufferedReader后,应将该br流传输到任何要用的方法中,而不是每一个方法中去分别创建流。
2)现在楼主就是要在方法中分别创建流(像现在这种情形:在service()方法中创建一个socket对应
的br流,在doPost()方法中对同一个socket,再创建一个socket对应的br流),又怎么样呢?
这就会出现楼主现在遇到的这种情况:好像读不到数据了。其真正的原因是什么?
是这样:
每一个方法中所创建的br流,其底层是同一个InputStream流,当我们在service()方法中创建br流时[其实只要创建InputStreamReader流时],由于这些流内部都是有缓冲的,因而,一旦在service()方法中发生了读操作,立即会导致底层InputStream读入大量数据。[内部缓冲是8K],这时我们在doPost()方法中再创建br进行读取时,已被service()方法中读走
的数据[8K],在doPost()中再也读不到了已被读走的数据。[只能读它之后的数据]这就是困绕楼主看到的情况[楼主误认为:好像是读不到数据了。]。对于楼主的情况,用()与reset()
是没有用的--它只对楼的br流有用,但是:[因为底层InputStreamReader中使用了StreamDecoder,它有默认8K的BUF缓冲]。因此:
结论:[怎么办?]
1)若楼主在service()中,创建了br流,但没有发生读操作,则此时doPost()中再创建br流读取,将一切正常。
2)若楼主在service()中,不创建任何底层内部带缓冲的流,直接使用原始的socket的InputStream进行
读操作,则此时doPost()中再创建br流读取,也将一切正常。
3)若楼主在service()中,创建任何底层内部带缓冲的流,即使使用()与reset(),因为它只是对内部带缓冲的流起作用,而不是对socket的InputStream起作用,一旦已发生读操作,则此时doPost()中再创建br流读取,将再也读不到了已被读走的数据。就会出现楼主现在遇到的这种情况:好像在doPost()读不到数据了。[其实不是,而是本来数据不多,
已全被读走了。]
4)规范的用法:一旦有了socket,创建它的I/O流,将该流传入到所有需要的方法中,而不是
每一个方法都自己来再创建流。
正在考虑是不是要新开一个帖子,你去签个名,我就把分数给你。
我先按照你说的修改一下代码;
但是我脑子里面还是有一个问题:
对于简单的doGet和doPost(没有附件),用Reader就够用了。因为他们没有带二进制的数据;
但是如果我要处理multipart的话,我必须要inputStream来读上传的文件,但同时我也要用Reader来读去开始的http头, 来解析一些必要的信息,
因为这些信息是一行一行的发送的,如果用stream来读取这些信息我不知道怎么解析。
DataInputStream既可以读行,也可以读byte, 但他的readLine不推荐使用了。
总结出来就是我不知道怎么用stream来读一个完整的行,并判断行结束了。
上传附件的问题解决了。但是现在post还是有一个问题, 我描述在程序中,谢谢大家再帮忙看看。
MyHttpServer.javapackage socket;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;public class MyHttpServer {
public static String WEB_ROOT = "c:/root";
private int port;
private String requestPath;
private String boundary = null;
private int contentLength = 0; public MyHttpServer(String root, int port) {
WEB_ROOT = root;
this.port = port;
requestPath = null;
} private void doGet(DataInputStream reader, OutputStream out) throws Exception {
if (new File(WEB_ROOT + this.requestPath).exists()) {
InputStream fileIn = new FileInputStream(WEB_ROOT + this.requestPath);
byte[] buf = new byte[fileIn.available()];
fileIn.read(buf);
out.write(buf);
out.close();
fileIn.close();
reader.close();
System.out.println("connection colsed");
}
} private void doPost(DataInputStream reader, OutputStream out) throws Exception {
//下面行出问题了, 如果不使用前面new的reader,用下面方式新开的reader读不到数据。
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
if ("".equals(line)) {
break;
} else if (line.indexOf("Content-Length") != -1) {
this.contentLength = Integer.parseInt(line.substring(line.indexOf("Content-Length") + 16));
}
//表明要上传附件, 跳转到doMultiPart方法。
else if(line.indexOf("multipart/form-data")!= -1){
//得multiltipart的分隔符
this.boundary = line.substring(line.indexOf("boundary") + 9);
this.doMultiPart(reader, out);
return;
}
}
//继续读取普通post(没有附件)提交的数据
System.out.println("begin reading posted data......");
String dataLine = null;
//这里出问题了:如果提交普通的post(不带附件),程序走到这里不走了;就是说没有读到数据,
//但是当我按浏览器ESC之后提交的数据正文就读出来了。
//dataLine = reader.readLine();
//我改为一个字符一个字符的读取也不可以。
char[] buf = {};
if (this.contentLength != 0) {
buf = new char[this.contentLength];
int size = 0;
char c = reader.readChar();
while(c!='\n'){
buf[size++] = c;
c = reader.readChar();
}
System.out.println("The data user posted: " + new String(buf, 0, size));
}
String response = "";
response += "HTTP/1.1 200 OK\n";
response += "Server: Sunpache 1.0\n";
response += "Content-Type: text/html\n";
response += "Last-Modified: Mon, 11 Jan 1998 13:23:42 GMT\n";
response += "Accept-ranges: bytes";
response += "\n";
String body = "<html><head><title>test server</title></head><body><p>post ok:</p>" + new String(buf) + "</body></html>";
System.out.println(body);
out.write(response.getBytes());
out.write(body.getBytes());
out.flush();
reader.close();
out.close();
} private void doMultiPart(DataInputStream reader, OutputStream out) throws Exception {
System.out.println("doMultiPart ......");
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
if ("".equals(line)) {
break;
} else if (line.indexOf("Content-Length") != -1) {
this.contentLength = Integer.parseInt(line.substring(line.indexOf("Content-Length") + 16));
System.out.println("contentLength: " + this.contentLength);
} else if (line.indexOf("boundary") != -1) {
//获取multipart分隔符
this.boundary = line.substring(line.indexOf("boundary") + 9);
}
}
System.out.println("begin get data......");
/*下面的注释是一个浏览器发送带附件的请求的全文,所有中文都是说明性的文字*****
<HTTP头部内容略>
............
Cache-Control: no-cache
<这里有一个空行,表明接下来的内容都是要提交的正文>
-----------------------------7d925134501f6<这是multipart分隔符>
Content-Disposition: form-data; name="myfile"; filename="mywork.doc"
Content-Type: text/plain
<附件正文>........................................
.................................................
-----------------------------7d925134501f6<这是multipart分隔符>
Content-Disposition: form-data; name="myname"<其他字段或附件>
<这里有一个空行>
<其他字段或附件的内容>
-----------------------------7d925134501f6--<这是multipart分隔符>
****************************************************************/
/**
* 上面的注释是一个带附件的multipart类型的POST的全文模型,
* 要把附件去出来,就是要找到附件正文的起始位置和结束位置
* **/
if (this.contentLength != 0) {
//把所有的提交的正文,包括附件和其他字段都先读到buf.
byte[] buf = new byte[this.contentLength];
int totalRead = 0;
int size = 0;
while (totalRead < this.contentLength) {
size = reader.read(buf, totalRead, this.contentLength - totalRead);
totalRead += size;
}
System.out.println("totalRead: " + totalRead);
//用buf构造一个字符串,可以用字符串方便的计算出附件所在的位置
String dataString = new String(buf, 0, totalRead);
System.out.println("data posted:\n" + dataString);
int pos = dataString.indexOf(boundary);
//以下略过4行就是第一个附件的位置
System.out.println("pos: " + pos);
pos = dataString.indexOf("\n", pos) + 1;
System.out.println("pos: " + pos);
pos = dataString.indexOf("\n", pos) + 1;
System.out.println("pos: " + pos);
pos = dataString.indexOf("\n", pos) + 1;
System.out.println("pos: " + pos);
pos = dataString.indexOf("\n", pos) + 1;
//附件开始位置
int start = dataString.substring(0, pos).getBytes().length;
pos = dataString.indexOf(boundary, pos) - 4;
System.out.println("pos: " + pos);
//附件结束位置
int end = dataString.substring(0, pos).getBytes().length;
//以下找出filename
int fileNameBegin = dataString.indexOf("filename") + 10;
int fileNameEnd = dataString.indexOf("\n", fileNameBegin);
String fileName = dataString.substring(fileNameBegin, fileNameEnd);
//
if(fileName.lastIndexOf("\\")!=-1){
fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
}
fileName = fileName.substring(0, fileName.length()-2);
OutputStream fileOut = new FileOutputStream("c:\\" + fileName);
fileOut.write(buf, start, end-start);
fileOut.close();
fileOut.close();
}
String response = "";
response += "HTTP/1.1 200 OK\n";
response += "Server: Sunpache 1.0\n";
response += "Content-Type: text/html\n";
response += "Last-Modified: Mon, 11 Jan 1998 13:23:42 GMT\n";
response += "Accept-ranges: bytes";
response += "\n";
out.write("<html><head><title>test server</title></head><body><p>Post is ok</p></body></html>".getBytes());
out.flush();
reader.close();
System.out.println("session closed.");
} public void service() throws Exception {
ServerSocket serverSocket = new ServerSocket(this.port);
System.out.println("server is ok.");
while (true) {
Socket socket = serverSocket.accept();
System.out.println("new request coming.");
DataInputStream reader = new DataInputStream((socket.getInputStream()));
String line = reader.readLine();
String method = line.substring(0, 4).trim();
OutputStream out = socket.getOutputStream();
this.requestPath = line.split(" ")[1];
System.out.println(method);
if ("GET".equalsIgnoreCase(method)) {
System.out.println("do get......");
this.doGet(reader, out);
} else if ("POST".equalsIgnoreCase(method)) {
System.out.println("do post......");
this.doPost(reader, out);
}
socket.close();
}
}
public static void main(String args[]) throws Exception {
MyHttpServer server = new MyHttpServer("c:/root", 8080);
server.service();
}
}upload.html: <测试上传附件用><html>
<head>
<title>my page</title>
<style>
table{
border-collapse: collapse;
}
</style>
</head>
<body>
<form action='http://localhost:8080' method='post' enctype='multipart/form-data'>
file: <input type='file' name='myfile' /><br>
name: <input type='text' name='myname' /><br>
<input type='submit' />
</form>
</body>
</html>post.html和13楼一样<测试普通post用>
确实是这样,处理HTTP头,需要字符流,但处理数据部分,需要字节流,怎么办?
实际上,HTTP协议是建立在字节流基础之上的。即:HTTP协议明确规定每一行是以CRLF结束的(即ACSII码13与ACSII码10)。因此:我想:可能的话,还是以字节流统一处理HTTP头部[因为:只有ASCII字符,不会有汉字的]。这样做的目的是:处理HTTP BODY部分时,只能是字节流。,因而HTTP头部与HTTP BODY就可以统一处理了。为什么在处理HTTP头部时,不能用BufferedReader来处理?还是那个缓冲问题。[它会把BODY部分的字节数据以字符流方式预先读入进来,这就会造成:以字符流方式处理字节流的HTTP BODY,可能会有问题]。以上仅供楼主参考
http://topic.csdn.net/u/20090627/22/4b19638d-378c-4fcd-bf7e-8536903ef9c8.htmlhttp://topic.csdn.net/u/20090627/22/4b19638d-378c-4fcd-bf7e-8536903ef9c8.html
1)楼主的整个doPost()与doMultiPart()没有严格按HTTP协议来写,这会有问题的。我认为要重新写。
2)现在首先针对楼主的那个小问题:“这里出问题了:如果提交普通的post(不带附件),程序走到这里不走了;就是说没有读到数据,”,原因或根源是什么?
还是因为楼主的代码没有按HTTP协议的规定要求写。将dopost()中的代码://这里出问题了:如果提交普通的post(不带附件),程序走到这里不走了;就是说没有读到数据,
//但是当我按浏览器ESC之后提交的数据正文就读出来了。
//dataLine = reader.readLine();
//我改为一个字符一个字符的读取也不可以。
char[] buf = {};
if (this.contentLength != 0) {
buf = new char[this.contentLength];
int size = 0;
char c = reader.readChar();
while(c!='\n'){
buf[size++] = c;
c = reader.readChar();
}
System.out.println("The data user posted: " + new String(buf, 0, size));
}
改为: byte[] buf = {};
if (this.contentLength != 0) {
buf = new byte[this.contentLength];
int size = 0;
while(size<this.contentLength){
int c = reader.read();
buf[size++] = (byte)c;
}
System.out.println("The data user posted: " + new String(buf, 0, size));
}则这个小问题就解决了。但我认为:整个doPost()与doMultiPart()要严格按HTTP协议来重写,这才是解决问题的根本之道。
早上起来发现帖子被推荐了。幸福啊, 第一次耶。感谢版主。
代码我都贴出来,真的很感谢jiangnaisong, jinxfei ,dengsf,以及其他的帮忙盖楼的朋友。
有兴趣的人看到代码,可以遵照http协议重写一下,如果有看不明白的地方,请回头看完整的帖子和http协议,其实这个东西实用性等于0, 但是可以大大的了解http协议。
然后其他的应用层协议大都如此。package socket;import java.io.*;
import java.net.*;
/**
* MyHttpServer 实现一个简单的HTTP服务器端,可以获取用户提交的内容
* 并给用户一个response
* 因为时间的关系,对http头的处理显得不规范
* 对于上传附件,暂时只能解析只上传一个附件而且附件位置在第一个的情况
* 转载请注明来自http://blog.csdn.net/sunxing007
* **/
public class MyHttpServer {
//服务器根目录,post.html, upload.html都放在该位置
public static String WEB_ROOT = "c:/root";
//端口
private int port;
//用户请求的文件的url
private String requestPath;
//mltipart/form-data方式提交post的分隔符,
private String boundary = null;
//post提交请求的正文的长度
private int contentLength = 0; public MyHttpServer(String root, int port) {
WEB_ROOT = root;
this.port = port;
requestPath = null;
}
//处理GET请求
private void doGet(DataInputStream reader, OutputStream out) throws Exception {
if (new File(WEB_ROOT + this.requestPath).exists()) {
//从服务器根目录下找到用户请求的文件并发送回浏览器
InputStream fileIn = new FileInputStream(WEB_ROOT + this.requestPath);
byte[] buf = new byte[fileIn.available()];
fileIn.read(buf);
out.write(buf);
out.close();
fileIn.close();
reader.close();
System.out.println("request complete.");
}
}
//处理post请求
private void doPost(DataInputStream reader, OutputStream out) throws Exception {
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
if ("".equals(line)) {
break;
} else if (line.indexOf("Content-Length") != -1) {
this.contentLength = Integer.parseInt(line.substring(line.indexOf("Content-Length") + 16));
}
//表明要上传附件, 跳转到doMultiPart方法。
else if(line.indexOf("multipart/form-data")!= -1){
//得multiltipart的分隔符
this.boundary = line.substring(line.indexOf("boundary") + 9);
this.doMultiPart(reader, out);
return;
}
}
//继续读取普通post(没有附件)提交的数据
System.out.println("begin reading posted data......");
String dataLine = null;
//用户发送的post数据正文
byte[] buf = {};
int size = 0;
if (this.contentLength != 0) {
buf = new byte[this.contentLength];
while(size<this.contentLength){
int c = reader.read();
buf[size++] = (byte)c;
}
System.out.println("The data user posted: " + new String(buf, 0, size));
}
//发送回浏览器的内容
String response = "";
response += "HTTP/1.1 200 OK\n";
response += "Server: Sunpache 1.0\n";
response += "Content-Type: text/html\n";
response += "Last-Modified: Mon, 11 Jan 1998 13:23:42 GMT\n";
response += "Accept-ranges: bytes";
response += "\n";
String body = "<html><head><title>test server</title></head><body><p>post ok:</p>" + new String(buf, 0, size) + "</body></html>";
System.out.println(body);
out.write(response.getBytes());
out.write(body.getBytes());
out.flush();
reader.close();
out.close();
System.out.println("request complete.");
}
//处理附件
private void doMultiPart(DataInputStream reader, OutputStream out) throws Exception {
System.out.println("doMultiPart ......");
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
if ("".equals(line)) {
break;
} else if (line.indexOf("Content-Length") != -1) {
this.contentLength = Integer.parseInt(line.substring(line.indexOf("Content-Length") + 16));
System.out.println("contentLength: " + this.contentLength);
} else if (line.indexOf("boundary") != -1) {
//获取multipart分隔符
this.boundary = line.substring(line.indexOf("boundary") + 9);
}
}
System.out.println("begin get data......");
/*下面的注释是一个浏览器发送带附件的请求的全文,所有中文都是说明性的文字*****
<HTTP头部内容略>
............
Cache-Control: no-cache
<这里有一个空行,表明接下来的内容都是要提交的正文>
-----------------------------7d925134501f6<这是multipart分隔符>
Content-Disposition: form-data; name="myfile"; filename="mywork.doc"
Content-Type: text/plain
<附件正文>........................................
.................................................
-----------------------------7d925134501f6<这是multipart分隔符>
Content-Disposition: form-data; name="myname"<其他字段或附件>
<这里有一个空行>
<其他字段或附件的内容>
-----------------------------7d925134501f6--<这是multipart分隔符,最后一个分隔符多两个->
****************************************************************/
/**
* 上面的注释是一个带附件的multipart类型的POST的全文模型,
* 要把附件去出来,就是要找到附件正文的起始位置和结束位置
* **/
if (this.contentLength != 0) {
//把所有的提交的正文,包括附件和其他字段都先读到buf.
byte[] buf = new byte[this.contentLength];
int totalRead = 0;
int size = 0;
while (totalRead < this.contentLength) {
size = reader.read(buf, totalRead, this.contentLength - totalRead);
totalRead += size;
}
//用buf构造一个字符串,可以用字符串方便的计算出附件所在的位置
String dataString = new String(buf, 0, totalRead);
System.out.println("the data user posted:\n" + dataString);
int pos = dataString.indexOf(boundary);
//以下略过4行就是第一个附件的位置
pos = dataString.indexOf("\n", pos) + 1;
pos = dataString.indexOf("\n", pos) + 1;
pos = dataString.indexOf("\n", pos) + 1;
pos = dataString.indexOf("\n", pos) + 1;
//附件开始位置
int start = dataString.substring(0, pos).getBytes().length;
pos = dataString.indexOf(boundary, pos) - 4;
//附件结束位置
int end = dataString.substring(0, pos).getBytes().length;
//以下找出filename
int fileNameBegin = dataString.indexOf("filename") + 10;
int fileNameEnd = dataString.indexOf("\n", fileNameBegin);
String fileName = dataString.substring(fileNameBegin, fileNameEnd);
/**
* 有时候上传的文件显示完整的文件名路径,比如c:\my file\somedir\project.doc
* 但有时候只显示文件的名字,比如myphoto.jpg.
* 所以需要做一个判断。
*/
if(fileName.lastIndexOf("\\")!=-1){
fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
}
fileName = fileName.substring(0, fileName.length()-2);
OutputStream fileOut = new FileOutputStream("c:\\" + fileName);
fileOut.write(buf, start, end-start);
fileOut.close();
fileOut.close();
}
String response = "";
response += "HTTP/1.1 200 OK\n";
response += "Server: Sunpache 1.0\n";
response += "Content-Type: text/html\n";
response += "Last-Modified: Mon, 11 Jan 1998 13:23:42 GMT\n";
response += "Accept-ranges: bytes";
response += "\n";
out.write("<html><head><title>test server</title></head><body><p>Post is ok</p></body></html>".getBytes());
out.flush();
reader.close();
System.out.println("request complete.");
} public void service() throws Exception {
ServerSocket serverSocket = new ServerSocket(this.port);
System.out.println("server is ok.");
//开启serverSocket等待用户请求到来,然后根据请求的类别作处理
//在这里我只针对GET和POST作了处理
//其中POST具有解析单个附件的能力
while (true) {
Socket socket = serverSocket.accept();
System.out.println("new request coming.");
DataInputStream reader = new DataInputStream((socket.getInputStream()));
String line = reader.readLine();
String method = line.substring(0, 4).trim();
OutputStream out = socket.getOutputStream();
this.requestPath = line.split(" ")[1];
System.out.println(method);
if ("GET".equalsIgnoreCase(method)) {
System.out.println("do get......");
this.doGet(reader, out);
} else if ("POST".equalsIgnoreCase(method)) {
System.out.println("do post......");
this.doPost(reader, out);
}
socket.close();
System.out.println("socket closed.");
}
}
public static void main(String args[]) throws Exception {
MyHttpServer server = new MyHttpServer("c:/root", 8080);
server.service();
}
}
post.html:测试提交的普通post请求.<html>
<head>
<title>test my server</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>upload</p> <form name="UploadForm" method="post" action="testupload.jsp">
<input type="text" name="myname" /><br>
<select name="myage">
<option value="18">18</option>
<option value="20">20</option>
<option value="22">22</option>
</select><br>
<input type="submit"value="Sutmit">
</form>
</body>
</html>upload.html:测试带一个附件的post.<head>
<title>my page</title>
<style>
table{
border-collapse: collapse;
}
</style>
</head>
<body>
<form action='submit.jsp' method='post' enctype='multipart/form-data'>
file: <input type='file' name='myfile' /><br>
<input type='submit' />
</form>
</body>
</html>
自己这段时间也准备复习socket,这个老师好啊,我们的老师上课都是照着课本读了一下,就结束了。
InputStream is = socket.getInputStream();
http://blog.csdn.net/sunxing007/archive/2009/06/29/4305956.aspx
我是用J2ME调用怎么response返回的信息都是空的
我是调用你的例子
还有没有一些HTTP开发的标准协议规范没?
如果有能发给我的Emial:[email protected]
谢谢
public class msbTree {
public static void main(String[] args){
File file = new File("C:/Documents and Settings/Admini" +
"strator/workspace/FileTree/src/a");
System.out.println(file.getName());
tree(file,1);
}
public static void tree(File file,int level){
String fr = "";
for(int k=0;k<level;k++){
fr += " ";
}
File[] children = file.listFiles();
for(int i=0;i<children.length ;i++){
System.out.println(fr+"/"+children[i].getName());
if(children[i].isDirectory()&&children[i].listFiles()!=null){
tree(children[i],++level);
}
}
}
}