本文以JAVA socket编程,实现http服务器,
http协议基础自行学习
不多说,上代码
Httpsimple类:
package css_nobody;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.JTextArea;
public class HttpSimpleServer implements Runnable{
private int port;//绑定端口号
private String Web_root;//html文件根目录
private ServerSocket serverSocket;//服务器套接字
private ExecutorService threadpool;//线程池
private Safty_JtextArea msgDisplayer;//展示信息
public HttpSimpleServer(int port,String web_root,Safty_JtextArea jt) {
this.port=port;
this.Web_root=web_root;
msgDisplayer=jt;
}
public boolean startServer() throws IOException {
serverSocket=new ServerSocket(port);
threadpool=Executors.newCachedThreadPool();
while(true){
Socket client= serverSocket.accept();
System.out.println("New client connection!");
System.out.println("address:"+client.getInetAddress().getHostAddress()+" "+client.getInetAddress().getHostName());
threadpool.execute(new ResponderServer(client,msgDisplayer,Web_root));//放入线程池中进行
}
}
@Override
public void run() {
try {
startServer();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
ResponderServer类
package css_nobody;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import javax.lang.model.element.Element;
import javax.swing.JTextArea;
public class ResponderServer implements Runnable{
private Socket clientsocket;//客户套接字
private InputStream dateFromClient;//写入流
private OutputStream dateToClient;//写出流
private Safty_JtextArea msgtxt;//消息显示区域
private String[] addressClient;//地址,端口
private Map<String, String> table;//请求/相应头部
private final int TIME_OUT =100000;//请求时间
private String web_root;//文件根目录
public ResponderServer(Socket client,Safty_JtextArea jt,String web_root) {
// TODO Auto-generated constructor stub
clientsocket=client;
this.web_root=web_root;
msgtxt=jt;
dateFromClient=null;
dateToClient=null;
addressClient=new String[2];
table=new HashMap<String,String>();
table.put("Date", "");//服务器日期
table.put("Server", "father of kongzhe");//服务器名称
table.put("Accept", "text/html");//接受请求类型
table.put("Content-Length", "");//相应正文长度
table.put("Last-Modified", "");//最后修改日期
table.put("Msg", "");//如果为测试客户端,这个将会返回测试客户端发送的内容+accept,表明通信协议正确
table.put("Cookies", "111");//一些标志身份的数据
}
@SuppressWarnings("finally")
@Override
public void run() {
//处理请求,发送结果,关闭输入输出流
boolean isgetted= getStream();
System.out.println("strem already get!!");
if(isgetted==false){
try {
clientsocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
return;
}
}//打开流失败,不连接
try {
clientsocket.setSoTimeout(TIME_OUT);//设置超时
} catch (SocketException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
BufferedInputStream bin=new BufferedInputStream(dateFromClient);
try {
LinkedList<Byte> alldatalist=new LinkedList<Byte>();//链表
int byteint;
queue lqueue=new queue(4);//最大大小
while((byteint=bin.read())!=-1){//有数据
System.out.println("read byte:"+byteint+" "+(char)byteint);
alldatalist.add(Byte.valueOf((byte)byteint));
if(canbebreak(lqueue, byteint)){break;}
//将信息全部读出来,放到队列里面
}
Byte[] bytearray_up=new Byte[alldatalist.size()];
alldatalist.toArray(bytearray_up);
byte[] bytearray=new byte[bytearray_up.length];
for(int i=0;i<bytearray_up.length;i++)bytearray[i]=bytearray_up[i].byteValue();//析构为byte
StringBuffer datestring=new StringBuffer(new String(bytearray));//创建一个缓冲字符串
System.out.println("alldata:"+datestring);
analysisAndResponde(datestring);//进行分析处理
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public boolean getStream() {
try {
dateFromClient= clientsocket.getInputStream();//输入liu
dateToClient=clientsocket.getOutputStream();
InetAddress intadd=clientsocket.getInetAddress();//
addressClient[1]=intadd.getHostAddress();
System.out.println("addressClient[1]"+addressClient[1]);
addressClient[0]=intadd.getHostName();
System.out.println("addressClient[0]"+addressClient[0]);
return true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
msgtxt.append(addressClient[0]+":"+addressClient[1]+"failed!");
return false;
}//输出流
}
private void analysisAndResponde(StringBuffer alldate){//分析Method,分布处理
int index=0;
if("GET".equalsIgnoreCase(alldate.substring(0, alldate.indexOf(" "))))//第一个空格之前的,为方法
{
index=alldate.indexOf(" ");
GetMethod(alldate, index);//进行get方法处理
}
else if("POST".equalsIgnoreCase(alldate.substring(0, alldate.indexOf(" ")))){
index=alldate.indexOf(" ");
PostMethod(alldate, index);//进行post 方法处理
}
else {
FaileMethod();//进行失败方法处理
}
}
private void GetMethod(StringBuffer alldate,int index){
String url= alldate.substring(index+" ".length(), alldate.indexOf(" ", index+" ".length()));//从第1个空格之后,截取一段直到第二个空格为止的字符串
Map<String, String> requestFromClient =new HashMap<String,String>();//表头以哈希表的形式放进去
index=alldate.indexOf("\r\n");//找到以第一个index
boolean isEnded=false;
while(isEnded==false){
String stringtemp=alldate.substring(index+"\r\n".length(),alldate.indexOf("\r\n",index+"\r\n".length()));//第一个\r\n之后开始变为一个新航
System.out.println("stringtemp1:"+stringtemp);
if(stringtemp==null || stringtemp.equals("") || stringtemp.length()<=0){
isEnded=true;//找到最后一行了
}
else{
String[] keyAndValues= stringtemp.split(":");
if(keyAndValues!=null && keyAndValues.length>=2){
System.out.println("key:"+keyAndValues[0]+" Values:"+keyAndValues[1]);
requestFromClient.put(keyAndValues[0], keyAndValues[1]);
}
else{
System.out.println("can not know");
}
index=alldate.indexOf("\r\n",index+"\r\n".length());//下一个行的开始
}
}//这些就放进去了
System.out.println("urlpath:"+web_root+url);
File f=new File(web_root+url);
if(f.exists()==false){//文件不存在
FaileMethod(requestFromClient);//访问失败
return;
}
try {
FileInputStream fin=new FileInputStream(f);//建立输入流
StringBuffer dateback=new StringBuffer();//建立输出数据的缓冲
byte[] bytedate=new byte[fin.available()];//
fin.read(bytedate);//读出来
fin.close();//关闭文件流
dateback.append(new String(bytedate));//将字符流变成字符串,输出到输出数据缓冲,这个缓冲是响应正文
String msgvalue=requestFromClient.get("Msg");
if(msgvalue!=null ){//
System.out.println("out!!"+msgvalue);
table.put("Msg", "acceptted:"+msgvalue);
}
table.put("Date",new SimpleDateFormat().format(new Date()));
table.put("Last-Modified", new SimpleDateFormat().format(new Date()));
table.put("Content-Length", ""+bytedate.length);//
String s="HTTP/1.0 200 0K\r\n"+MapToString(table)+"\r\n"+dateback.toString();
dateToClient.write(s.getBytes());//写出去
dateToClient.flush();//刷新
clientsocket.shutdownOutput();
String allmsg=MapToString(requestFromClient);
msgtxt.setText(msgtxt.getText()+ "来自("+addressClient[0]+":"+addressClient[1]+")的请求头:\r\n"+allmsg);
//clientsocket.close();//结束服务
} catch (FileNotFoundException e) {
e.printStackTrace();
}
catch(IOException e1){
e1.printStackTrace();
}
}
private void PostMethod(StringBuffer alldate,int index){
GetMethod(alldate, index);//暂时按get处理
}
private void FaileMethod(Map<String, String> requestFromClient){
table.put("Date",new SimpleDateFormat().format(new Date()));
table.put("Last-Modified", new SimpleDateFormat().format(new Date()));
table.put("Content-Length", ""+0);//
String s="HTTP/1.0 404 Not Found\r\n"+MapToString(table)+"\r\n";
String allmsg=MapToString(requestFromClient);
msgtxt.append("来自("+addressClient[0]+":"+addressClient[1]+")的请求头:\r\n"+allmsg);
try {
dateToClient.write(s.getBytes());//写出去
dateToClient.flush();
clientsocket.shutdownOutput();
//clientsocket.close();
} catch (IOException e) {
// TODO: handle exception
}
}
private void FaileMethod(){
table.put("Date",new SimpleDateFormat().format(new Date()));
table.put("Last-Modified", new SimpleDateFormat().format(new Date()));
table.put("Content-Length", ""+0);//
String s="HTTP/1.0 404 Not Found\r\n"+MapToString(table)+"\r\n";
String allmsg="UNknow request!\r\n";
msgtxt.append("来自("+addressClient[0]+":"+addressClient[1]+")的请求头:\r\n"+allmsg);
try {
dateToClient.write(s.getBytes());//写出去
clientsocket.shutdownOutput();
//clientsocket.close();
} catch (IOException e) {
// TODO: handle exception
}
}
private String MapToString(Map<String, String> map){
if(map==null)return "";
String s=new String();
for(Map.Entry<String, String> entry:map.entrySet()){
s+=entry.getKey()+":"+entry.getValue()+"\r\n";
}
return s;
}
private boolean canbebreak(queue lqueue,int byteint){
lqueue.Enqueue(byteint);
if(lqueue.getnowsize()>=4){
System.out.println(lqueue.getIndexOf(0)+" "+lqueue.getIndexOf(1)+" "+lqueue.getIndexOf(2)+" "+lqueue.getIndexOf(3)+" ");
if(lqueue.getIndexOf(0)==13 && lqueue.getIndexOf(1)==10 && lqueue.getIndexOf(2)==13 && lqueue.getIndexOf(3)==10){
return true;
}
else {
lqueue.dequeue();
return false;
}
}
return false;
}
class queue {
public int maxsize;
public int nowsize;
public node tail;
public node top;
public queue(int num){
nowsize=0;
maxsize=num;
tail=top=null;
}
public boolean Enqueue(int dataitem){
node newnode=new node(dataitem);
if(top==null){
tail=top=newnode;
nowsize++;
return true;
//缓冲队列为空
}
else{
if(nowsize>=maxsize)return false; //缓冲已满,已有100个
node oldn=tail;
tail.setnext(newnode); //放入队未
tail=newnode; //重置末尾指针
tail.setprev(oldn);
nowsize++; //增一
return true;
}
}
public node dequeue() {//
if(top==null)return null;//空表
else {
if(top==tail){ //只有一个
node n=top; //取出来
nowsize--; //数量减一
top=tail=null;
return n; //返回
}
else { //不止一个
node n=top;
top=top.getnext();
top.setprev(null); //把第一个取出来,
nowsize--; //数量减一
return n;//返回取出的
}
}
}
public boolean isFull(){return nowsize==maxsize;}
public int getnowsize(){return nowsize;}
public int getIndexOf(int index){
if(nowsize>=index+1){
node n=top;
for(int i=0;i<index;i++){
n=n.getnext();
}
return n.getdata();
}
else {
return -1;
}
}
}
class node{
public int dataitem;
public node next;
public node prev;
public node(int data){
dataitem=data;
next=null;
prev=null;
}
public int getdata(){return dataitem;}
public node getnext() {return next;}
public void setnext(node n) { next=n;}
public node getprev() {return prev;}
public void setprev(node n) { prev=n;}
}
}
前端代码和测试我就不贴了,可自行删除掉jtextArea,关键部分注释很到位,我在工程根目录下html文件夹放2个html文件,均可以正常访问
具体代码可留邮箱