手写服务器(二)

封装

1、Response

2、Request

3、多线程处理

 

一、封装Response

CloseUtil.java (关闭流的方法)

package cn.server;


import java.io.Closeable;
import java.io.IOException;

/*
 * 关闭流的方法
 */
public class CloseUtil {
    public static void closeAll(Closeable... io) {
        for(Closeable temp:io) {
                try {
                    if(null!=temp) {
                    temp.close();
                } 
                }    catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                
            }
        }
    }
}

Response.java (封装Response)

package cn.server;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Date;

/*
 * 封装响应信息
 */
public class Response {
    public static final String CRLF="\r\n";
    public static final String BLANK=" ";
    //
    private BufferedWriter bw;
    //正文
    private StringBuilder content;
    //存储头信息    
    private StringBuilder headInfo;
    //存储正文长度
    private int len=0;
/*
 * 构建响应头
 */
    public Response() {
        headInfo=new StringBuilder();
        content=new StringBuilder();
        len=0;
    }
    public Response(Socket client) {
        this();
        try {
            bw=new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            headInfo=null;
        }
    }
    public Response(OutputStream os) {
        this();
        bw=new BufferedWriter(new OutputStreamWriter(os));
    }
    
    /*
     * 构建正文
     */
    public Response print(String info) {
        content.append(info);
        len+=info.getBytes().length;
        return this;
    }
    
    /*
     * 构建正文+回车
     */
    public Response println(String info) {
        content.append(info).append(CRLF);
        len+=(info+CRLF).getBytes().length;
        return this;
    }
    
    private void createHeadInfo(int code) {
        //1)http协议版本、状态代码    、描述
        headInfo.append("HTTP/1.1").append(BLANK).append(code).append(BLANK);
        switch(code) {
        case 200:
            headInfo.append("ok");
            break;
        case 404:
            headInfo.append("NOT FOUND");
            break;
        case 500:
            headInfo.append("SEVER ERROR");
            break;
        }
        
        headInfo.append(CRLF);
        
        //2)响应头(response Head)
        headInfo.append("sun").append(CRLF);
        headInfo.append("Date").append(new Date()).append(CRLF);
        headInfo.append("Content-type:text/html;charset=GBK").append(CRLF);
        //正文的长度 :字节长度
        headInfo.append("Content-Length:").append(len).append(CRLF);
        headInfo.append(CRLF); //分隔符
    }
    //推送到客户端
    void pushToClient(int code) throws IOException {
        if(headInfo==null) {
            code=500;
        }
        createHeadInfo(code);
        //头信息+分割符
        bw.append(headInfo.toString());
        //正文
        bw.append(content.toString());
        bw.flush();
    }
    public void close() {
        CloseUtil.closeAll(bw);
    }
}

Server4.java (调用)

package cn.server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;

/*
 * 创建服务器,并启动
 * 请求并响应
 */
public class Server4 {
    private ServerSocket server;
    public static final String CRLF="\r\n";
    public static final String BLANK=" ";
    public static void main(String[] args) {
        Server4 server=new Server4();
        server.start();
    
        
    }
    //启动方法
    public void start() {
        
        try {
            server = new ServerSocket(8660);
            
            
            this.receive();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
    
    /*
     * 接收客户端
     */
    private void receive() {
        try {
            Socket client=server.accept();
            
            String msg=null; 
            
            byte[] data=new byte[20480];
            int len=client.getInputStream().read(data);
             //接收客户端的请求信息    
            String requestInfo=new String(data,0,len).trim();
            System.out.println(requestInfo);
            
            //响应

            Response rep=new Response(client);
            rep.println("<html><head><title>http响应实例</title><head>" );
            rep.println("<body><p></p>Hello Server!</body></html>");
            rep.pushToClient(200);
            
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /*
     * 停止服务器
     */
    public void stop() {
        
    }
}

 二、封装Request   (解决中文乱码问题)

Request.java (封装Request)

package cn.server;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
/*
 * 封装Request
 */
public class Request {
    //请求方式
    private String method;
    //请求资源
    private String url;
    //请求参数
    private Map<String,List<String>> parameterMapValues;
    
    //内部
    public static final String CRLF="\r\n";
    private InputStream is;
    private String requestInfo;
    
    public Request() {
        method="";
        url="";
        parameterMapValues=new HashMap<String,List<String>>();
        requestInfo="";
    }
    public Request(InputStream is) {
        this();
        this.is=is;
        
        try {
            byte[] data=new byte[20480];
            int len = is.read(data);
            requestInfo=new String(data,0,len);
        } catch (IOException e) {
            return ;
        }
        //分析头信息
        paseRequestInfo();
        
    }
    /*
     * 分析请求信息
     */
    private void paseRequestInfo() {
        if(null==requestInfo ||(requestInfo=requestInfo.trim()).equals("")) {
            return ;
        }
        /*
         * 从信息的首行分解出:请求方式        请求路径    请求参数(get可能存在)
         * 
         * 
         */
        String paramString="";//接收请求参数
        //1、获取请求方式
        String firstLine=requestInfo.substring(0,requestInfo.indexOf(CRLF));
        int idx=requestInfo.indexOf("/");   //  /的位置
        this.method=firstLine.substring(0,idx).trim();
        String urlStr=firstLine.substring(idx,firstLine.indexOf("HTTP/")).trim();
        if(this.method.equalsIgnoreCase("post")) {
            this.url=urlStr;
            paramString=requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim();
        }else if(this.method.equalsIgnoreCase("get")) {
            if(urlStr.contains("?")) {   //是否存在参数
                String[] urlArray=urlStr.split("\\?");
                this.url=urlArray[0];
                paramString=urlArray[1];  //接收请求参数
            }else {
                this.url=urlStr;
            }
        }
        //2、将请求参数封装到Map中
        //如果paramString请求参数不存在
        if(paramString.equals("")) {
            return ;
        }
        parseParams(paramString);
    }
    private void parseParams(String paramString) {
        //分割  将字符串转成数组
        StringTokenizer token=new StringTokenizer(paramString,"&");
        while(token.hasMoreTokens()) {
            String keyValue=token.nextToken();
            String[] keyValues=keyValue.split("=");     //[uname,123]
            if(keyValues.length==1) {
                keyValues=Arrays.copyOf(keyValues, 2); //数组拷贝  keyValues=[uname]  把以前的值放进去,长度变为2
                keyValues[1]=null;
            }
            String key =keyValues[0].trim();
            String value=keyValues[1]==null?null:decode(keyValues[1].trim(),"utf-8");
            //转换成Map,分拣
            if(!parameterMapValues.containsKey(key)) {
                parameterMapValues.put(key,new ArrayList<String>());
            }
            List<String> values=parameterMapValues.get(key);
            values.add(value);   //{uname=[123],pwd=[213],fav=[1],fav=[2]
            
        }

    }
    /*
     * 解决中文乱码
     * 解码
     */
    private String decode(String value,String code) {
        try {
            return java.net.URLDecoder.decode(value,code);
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            
        }
        return null;
    }
    /*
     * 根据页面的 name获取对应的多个值
     */
    public String[] getParametervalues(String name) {
        List<String> values=null;
        values=parameterMapValues.get(name);
        if(values==null) {
            return null;
        }else {
            return values.toArray(new String[0]);    //将list转变为数组
        }
    }
    /*
     * 根据页面的 name获取对应的值
     */
    public String getParameter(String name) {
        String[] values=getParametervalues(name);
        if(values==null) {
            return null;
        }
        return values[0];
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    
    
}

Server5.java (调用)

package cn.server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;

/*
 * 创建服务器,并启动
 * 请求并响应
 */
public class Server5 {
    private ServerSocket server;
    public static final String CRLF="\r\n";
    public static final String BLANK=" ";
    public static void main(String[] args) {
        Server5 server=new Server5();
        server.start();
    
        
    }
    //启动方法
    public void start() {
        
        try {
            server = new ServerSocket(8290);
            
            
            this.receive();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
    
    /*
     * 接收客户端
     */
    private void receive() {
        try {
            Socket client=server.accept();
            
            String msg=null; 
            //请求
            Request req=new Request(client.getInputStream());
            
            
            //响应

            Response rep=new Response(client);
            rep.println("<html><head><title>http响应实例</title>" );
            rep.println("<head><body>");
            rep.println("欢迎:").println(req.getParameter("uname")).println("回来");
            rep.println("</body></html>");
            rep.pushToClient(200);
            
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /*
     * 停止服务器
     */
    public void stop() {
        
    }
}

效果:

 

posted on 2019-08-08 11:18  Mentality  阅读(260)  评论(0编辑  收藏  举报