由于项目的需求,需要实现以下流程:
1. Client发送HTTP请求到Server.
2. Server接收HTTP请求并显示出请求的内容(包含请求的头及Content的内容)
Server部分代码如下:
import java.net.Socket; import java.net.ServerSocket; import java.net.InetAddress; import java.io.InputStream; import java.io.OutputStream; import java.io.IOException; /** * * @author Anson */ public class Server{ private String ServerIP; private int ServerPort; private boolean shutdown = false; /** * Init Server */ public void init(){ ServerIP = "192.168.0.1"; ServerPort = 8082; } /** * */ public void await(){ ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(ServerPort, 1, InetAddress.getByName(ServerIP)); }catch (IOException e) { e.printStackTrace(); System.exit(1); } // Loop waiting for a request while(!shutdown){ Socket socket = null; InputStream input = null; OutputStream output = null; try { socket = serverSocket.accept(); input = socket.getInputStream(); output = socket.getOutputStream(); this.parse(input); // Close the socket socket.close(); }catch (Exception e) { e.printStackTrace(); continue; } } } public void parse(InputStream input) { // Read a set of characters from the socket StringBuffer request = new StringBuffer(2048); int i; byte[] buffer = new byte[2048]; try { i = input.read(buffer); }catch (IOException e) { e.printStackTrace(); i = -1; } for (int j=0; j<i; j++) { request.append((char) buffer[j]); } System.out.println(request.toString()); } }
再编写StartServer.java
.... public class StartServer{ public static void main(String[] args){ Server server = new Server(); server.init(); server.await(); ..... } }
跟着,客户端的代码做法有很多,
可以用最简单的Socket,
也可以用HttpClient,
或其它客户端如:OC
具体做法,网上有很多,在此不细述.
我用的是OC,
当然,可能有些做法,并不会出现这样的问题,
毕竟,我,并非一个高手.
我只描述我遇到的状况,
成功实现的可以忽略.
当客户端发送的数据量小于一定长度(如2048byte)的时候,
Server运行正常,即可以正常打印出请求的内容.
如:GET index HTTP/1.1
........
请求的头加上一些Content.
但当数据量大于2048的时候,奇怪的问题出现了.
有时会发现数据读不全.
例如,在请求的头下面,Content的内容是一串XML的String:
<?xml version="1.0" encoding="UTF-8" ?><label1>label1></label1>......
当请求的头加上XML的String的总长度超过2048,那么,可能出现在情况就是超过的部分丢失.
可能已经有人发觉,在上面的Server里面的parse(InputStream input)这里的处理有问题.
因为很大程度上这个2048在StringBuffer的定义时就出现了.
所以,第一个失败的尝试便是修改2048.
第一次变成10*2048
跟着是100*2048....
最后是1000*2048....
但结果可以发现:数据量的限制并不会随着这个数值的成倍增长而以相同倍数增长.有时可能是为了增加一倍,
而这个数值必需增加20倍.....
最后发现这个办法不可能,
于是,改变了读取的办法.
用了其它的如StreamBufferReader还有很多其它的来尝试读取,
结果却令人失望,
甚至于这时候出现了阻塞.
即,在读取的过停中,卡住了,
直到等到客户端的请求超时,才跳出来.
所以这些方法也失败了.
具体的情况也记不大清楚了.
之后的另一个方法:
String request = "";
//如果不先读一次,那么下面的input.available()有可能是0值.
char firstbyte = (char) input.read();
request += firstbyte;
int ava = 0;
while ((ava = input.available()) > 0) {
try {
// 在此睡眠0.1秒,很重要
Thread.sleep(100);
} catch (Exception t) {
t.printStackTrace();
}
byte[] bufferedbyte = new byte[ava];
input.read(bufferedbyte, 0, ava);
request += new String(bufferedbyte, "UTF-8");
}
这是一个成功解决的方法,
之所以要睡眠0.1秒,等待高手帮忙解答,
这也许跟网络有关系,
当然,数据量越大,睡眠的时应该有小小的加长.(缓冲时间).
虽然以上的做法成功实现了,但对于服务器来说,效率是个问题,所以只能寻找更优的办法.
第三次更改:
int readInt = 0; int availableCount = 0; char requestHead = (char)(input.read()); request += requestHead;
//取得请求的类型是PUT或GET if(requestHead == 'P') {//主要是PUT的方法里面会带有XML. while((readInt=input.read()) != -1) { request += (char)readInt; if(request.indexOf("</endXML>") != -1){ break; } } System.out.println("this is put\n" +request); } else if(requestHead=='G') {//GET的方法内容比较少,用以下的方法可以正常实现 while((availableCount=input.available()) > 0){ byte[] requestbuffer = new byte[availableCount]; input.read(requestbuffer); request += new String(requestbuffer, "UTF-8"); }
*代码并不完整.
这种做法,我在读取XML的String里加上了一个结束的判断即对"</endXML>"的判断(当然,这是在知道Content内容的基础上这种做法才可行).
虽然暂时解决了问题,但仍然不能完美解决存在的问题.
第四次更改:
这也是最后一次更改,办法是:
在PUT的请求里面,先取得一个Content-Length:的请求头的值length.
这里的大小就是Content的长度.
在这个基础上,
先判断是否开始读取Content:
if(requestString.indexOf("\r\n\r\n") != -1)
.....
之后再循环读取:
for(int i=0; i < length; i++){
requestString += (char)input.read();
}
当读完length后,跳出循环,
并跳出读取input的读取.
.......
问题在此告一段落.
若有哪位朋友懂得其中原理,恳请告知,
知其然而不知其所以然,心里不免有个结.
以上做法,仅供参考.
若有错误,请不啬指出.
欢迎转载
转载进请注明转自:http://ansonlai.iteye.com