Java 从底层socket实现http服务器

本文以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文件,均可以正常访问
具体代码可留邮箱

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值