浏览器与服务端的通信01
来源:互联网 发布:如何防止sql攻击 编辑:程序博客网 时间:2024/05/16 00:25
在pom.xml中导入两个jar包:jaxen1.1.4和dom4j1.6.1
WebServer类:
/** * 基于Http协议的Web服务端程序 * @author live */public class WebServer { private ServerSocket server; /* * 线程池,管理用于处理客户端请求的线程 */ private ExecutorService threadPool; /** * 构造方法,用于初始化服务端程序 * @throws Exception */ public WebServer() throws Exception{ try{ server=new ServerSocket(ServerContent.ServerPort); threadPool=Executors.newFixedThreadPool(ServerContent.max_thread); }catch(Exception e){ throw e; } } public void start(){ try{ while(true){ System.out.println("等待客户端连接"); Socket socket=server.accept(); System.out.println("客户端已连接"); /* * 将处理该客户端请求的任务交给线程池 */ threadPool.execute(new ClientHandler(socket)); } }catch(Exception e){ e.printStackTrace(); } } public static void main(String[] args) {try{WebServer server=new WebServer();server.start();}catch(Exception e){e.printStackTrace();System.out.println("服务端启动失败!");}} }
ClientHandler类:
/** * 处理客户端请求 * @author live * */public class ClientHandler implements Runnable{private Socket socket;public ClientHandler(Socket socket){this.socket=socket;}public void run(){try{/* * HTTP协议中的请求信息格式: * 请求行 资源 协议 换行 * GET/index.html HTTP1.1 CRLF(请求方式) POST * 消息报头 * 消息正文 * * 以行为单位发送至服务端 每行结尾以(CR LF) * CR:回车 LF:换行 * http://localhost:8080 */ //获取输入流,读取客户端发送过来的数据InputStream in=socket.getInputStream(); OutputStream out=socket.getOutputStream(); //读取一行字符串,请求行信息//Method Request-URI Http-version(CRLF)//如://GET/index.html HTTP/1.1CRLF//生成HttpRequest表示请求信息HttpRequest request=new HttpRequest(in);HttpResponse response=new HttpResponse(out);if(request.getUri()!=null){File file=new File(ServerContent.web_root+request.getUri()); if(file.exists()){ //设置状态行 response.setStatus(HttpContent.STATUS_CODE_OK); //设置响应头 response.setContentType(getContentTypeByFile(file)); responseFile(file,response); response.setContentLength((int)file.length()); System.out.println("响应客户端完毕!"); }else{ //响应客户端没有该资源(显示个错误页面) response.setStatus(HttpContent.STATUS_CODE_NOT_FOUND); //错误页面 file=new File(ServerContent.web_root+File.separator+ServerContent.notFoundPage);//"/notfound.html" response.setContentType(getContentTypeByFile(file)); response.setContentLength((int)file.length()); responseFile(file,response); }} }catch(Exception e){e.printStackTrace();/* * 505 */}finally{try{socket.close();}catch(Exception e){e.printStackTrace();}}}/** * 根据给定的文件获取对应的Content-Type * @param file * @return */private String getContentTypeByFile(File file){/** * 1:首先获取该文件的名字 * 2:获取该文件名的文件类型(文件名的后缀) * 3:根据类型名从ServerContent的types中作为key获取对应的Content-Type */String filename=file.getName();String ext=filename.substring(filename.lastIndexOf(".")+1);String contentType=ServerContent.types.get(ext);System.out.println("contentType:"+contentType);return contentType;}/** * 响应文件 * @param file * @param response * @throws Exception */public void responseFile(File file,HttpResponse res) throws Exception{BufferedInputStream bis=null;try{/* * 将该文件中每个字节通过客户端输出流发送给服务端 */ bis=new BufferedInputStream( new FileInputStream(file));/* * 通过Response取出输出流,这里就自动发发送 * 了状态行和响应头 */OutputStream out=res.getOutputStream();int d=-1;while((d=bis.read())!=-1){out.write(d);}}catch(IOException e){throw e;}finally{if(bis!=null){bis.close();}}} }
HttpContent类:
/** * 定义HTTP协议中的相关信息 * @author live * */public class HttpContent {/* * 回车 */public static final int CR=13;/* * 换行 */public static final int LF=10;/** * 状态码:成功 */public static final int STATUS_CODE_OK=200;/** * 状态描述:成功 */public static final String STATUS_VALUE_OK="Ok";/** * 状态代码:未找到 */public static final int STATUS_CODE_NOT_FOUND=404;/** * 状态描述:未找到 */public static final String STATUS_VALUE_NOT_FOUND="Not Found";/** * 状态代码:错误 */public static final int STATUS_CODE_ERROR=500;/** * 状态描述:错误 */public static final String STATUS_VALUE_ERROR="Internal Server Error";}
ServerContent类:
/** * 记录服务端相关信息 * @author live */public class ServerContent {/* * 服务端口 */public static int ServerPort;//服务端最大并发数public static int max_thread;//服务端应用根目录public static String web_root;/* * 服务器使用的Http协议的版本 */public static String protocol;//根据媒体文件后缀对应Content-Type的类型public static Map<String,String> types=new HashMap<String,String>();/* * 404页面 */public static String notFoundPage;static{//初始化 ServerContent的静态init();}/** * 加载server.xml文件对ServerContent进行初始化 */private static void init(){ try{ SAXReader reader=new SAXReader(); Document doc=reader.read(new FileInputStream( "config"+File.separator+"server.xml")); Element root=doc.getRootElement(); //解析<service> Element serviceEle=root.element("service"); //解析<connector> Element connEle=serviceEle.element("connector"); protocol=connEle.attributeValue("protocol"); System.out.println("protocol:"+protocol); ServerPort=Integer.parseInt( connEle.attributeValue("port")); System.out.println(" ServerPort:"+ ServerPort); max_thread=Integer.parseInt( connEle.attributeValue("maxThread")); System.out.println(" max_thread:"+ max_thread); //解析<webroot> web_root=serviceEle.elementText("webroot"); System.out.println(" web_root:"+ web_root); //解析<not-found-page> notFoundPage=serviceEle.elementText("not-found-page"); System.out.println("not-found-page:"+ notFoundPage); /* * 解析<type-mappings> */ Element mappingsEle=root.element("type-mappings"); List<Element> mappingsList=mappingsEle.elements(); for(Element mapping:mappingsList){ types.put(mapping.attributeValue("ext"), mapping.attributeValue("type")); } System.out.println("types:"+types); }catch(Exception e){ e.printStackTrace(); }}}
HttpRequest类:
/* * 封装Http请求相关内容 */public class HttpRequest {//请求方法 private String method; //请求资源 private String uri; //请求协议 private String protocol; /* * 构造方法,用于创建HttpRequest实例 * * @param in 对应客户端输入流,通过该流读取客 * 户端发送过来的请求信息并封装到当前HttpRequest对象中 */ public HttpRequest(InputStream in){ /* * HTTP协议中的请求信息格式: * 请求行 资源 协议 换行 * GET/index.html HTTP1.1 CRLF(请求方式) POST * 消息报头 * 消息正文 * * 以行为单位发送至服务端 每行结尾以(CR LF) * CR:回车 LF:换行 * http://localhost:8080 */ try{ //读取一行字符串,请求行信息//Method Request-URI Http-version(CRLF)//如://GET/index.html HTTP/1.1CRLF String line=readline(in); if(line.length()>0){ String[] data=line.split("\\s"); method=data[0]; uri=data[1]; protocol=data[2]; } }catch(IOException e){ e.printStackTrace(); } } /** * 从给定的输入流中读取一行字符窜并返回。 * 当读取到CR LF时认为一行结束 * 13 10 * * @param in * @return * @throws IOException */ private String readline(InputStream in)throws IOException{/* * 顺序的从流中读取每个字节并转换为对应的字符 * 然后拼接在一起,直到连续读取了CR LF时停止 * 并将拼接的字符串返回 */ StringBuilder builder=new StringBuilder(); try{ int ch1=-1,ch2=-1; while((ch2=in.read())!=-1){ if(ch1==HttpContent.CR&&ch2==HttpContent.LF){ break; } builder.append((char)ch2); ch1=ch2; } return builder.toString().trim(); }catch(IOException e){ throw e; } }public String getMethod() {return method;}public String getUri() {return uri;}public String getProtocol() {return protocol;} }
HttpResponse类:
/** * 封装Http响应 * HTTP响应格式 * 1:状态行 * 2:响应头 * 3:响应正文 * * 状态由3部分组成:协议版本,数字形式的状态代码,状态描述 * 格式:Http_Version Status-code Reason-Phrase CRLF * * 例如:HTTP/1.1 200 OK CRLF * * 状态代码第一个数字有5种: * 1xx:指示信息,表示请求已接收,继续处理。 * 2xx:成功,表示请求已接收,理解,接受 * 3xx:重定向,要完成请求需要更进一步的操作 * 4xx:客户端错误,请求语法错误或请求无法实现 * 5xx:服务端错误,服务端未能实现该请求 * 常见的状态码及描述: * 200 OK 客户端请求成功 * 400 Bad Request 客户端请求有语法错误,服务端不能理解 * 401 Unauthonzed 请求未授权 * 403 Forbidden 服务端收到请求,但是拒绝提供服务 * 404 Not Found 请求的资源不存在 * 500 Internal Server Error 服务器发生了不可预期的错误 * 503 Service Unavailable 服务器当前不能够处理客户端请求 * * 回应客户端对应的资源 * HTTP中响应的格式: * 1:状态行 * 2:响应头 * 3:响应正文 * 状态行格式: * HTTP-Version Status_code Reason_phrase CRLF * HTTP协议 状态代码 状态描述CRLF * 例如: * HTTP/1.1 200 OK CRLF * 2:响应头 * 响应头注明很多返回的信息,按行输出 * 常见: * Content-Type:用来指明发送给接收者的媒体类型 * 常见的Content-Type: * text/html:HTML格式文件(网页) * text/xml:XML格式文件 * image/gif:gif格式图片 * image/jpeg:jpeg格式图片 * image/png:png格式图片 * Content-Length,用来指明发送给接受者实体正文的长度 * 简单的说就是发送过去的数据的字节量 * * HTTP协议要求实际响应客户端时的数据格式: * HTTP/1.1 200 OK CRLF 状态行 * Content-Type:text/html CRLF 响应头信息 * Content-Length:100CRLF 响应头信息 * CRLF 单独发送CRLF指明响应头全部发送完毕 * DATA 实际数据 * TLD type length data * * @author live */public class HttpResponse {private OutputStream out;/* * 响应格式中所需要的信息 */private int status;//状态行中的状态代码private String contentType;//响应头中的正文类型private int contentLength;//响应头中的正文长度//表示响应状态行以及响应头信息是否已经发送过private boolean hasPrintHeader;//记录所有可用状态码及描述。private Map<Integer,String> statusMap;/* * 构造方法 * @param out 对应客户端的输出流,通过该输出流 * 将消息响应给客户端 */ public HttpResponse(OutputStream out){ this.out=out; statusMap=new HashMap<Integer,String>(); statusMap.put(HttpContent.STATUS_CODE_OK,HttpContent.STATUS_VALUE_OK); statusMap.put(HttpContent.STATUS_CODE_NOT_FOUND,HttpContent.STATUS_VALUE_NOT_FOUND); statusMap.put(HttpContent.STATUS_CODE_ERROR,HttpContent.STATUS_VALUE_ERROR); }public OutputStream getOutputStream() throws Exception {if(!hasPrintHeader){/* * 获取输出流前,将状态行,响应头信息自动发送 *///发送状态行 println(ServerContent.protocol+" "+status+" "+statusMap.get(status));//发送响应头信息 println("ContentType:"+contentType); println("ContentLength:"+contentLength); println("");//单独发送空行表示响应头发送完毕hasPrintHeader=true;}return out;}public int getStatus() {return status;}public void setStatus(int status) {this.status = status;}public String getContentType() {return contentType;}public void setContentType(String contentType) {this.contentType = contentType;}public int getContentLength() {return contentLength;}public void setContentLength(int contentLength) {this.contentLength = contentLength;}public Map<Integer, String> getStatusMap() {return statusMap;}/* * 将给定的一行字符串以HTTP协议格式要求按行写出 */private void println(String str) throws Exception{try {out.write(str.getBytes("ISO8859-1"));out.write(HttpContent.CR);out.write(HttpContent.LF); } catch (UnsupportedEncodingException e) {e.printStackTrace();System.out.println("不受支持的编码");throw e;} catch (IOException e) {e.printStackTrace();throw e;}}}
server配置文件:
<?xml version="1.0" encoding="UTF-8"?><server> <service> <connector protocol="HTTP/1.1" port="8888" maxThread="100"/> <webroot>webapps</webroot> <not-found-page>notfound.html</not-found-page> </service> <!-- 不同媒体类型对应的Content-Type值 --><type-mappings> <type-mapping ext="html" type="text/html"/> <type-mapping ext="png" type="image/png"/> <type-mapping ext="xml" type="text/xml"/> <type-mapping ext="jpeg" type="image/jpeg"/> <type-mapping ext="gif" type="image/gif"/> <type-mapping ext="ico" type="image/ico"/></type-mappings></server>
阅读全文
1 0
- 浏览器与服务端的通信01
- 浏览器与服务端的通信
- 浏览器与服务端通信
- C#与Flash通信的服务端程序
- 简单的服务端与客户端通信代码
- 基于WebSocket的Android与服务端通信
- 客户端与服务端的Socket通信
- socket客户端与服务端的通信
- sokect服务端与客户端的通信
- 浏览器与服务器的通信
- flex4与服务端通信
- as3与服务端通信
- 警察与小偷的实现之一客户端与服务端通信
- MFC_SOCKET_关于socket的服务端与客户端的通信
- 使用简单的ServiceSockt实现服务端与客户端的通信
- WinSocket实现的服务端与客户端的通信
- as3 与 服务端ASP 通信
- android如何与服务端通信
- Python高级教程之动态添加属性及方法
- STL 源码阅读
- 新版本的mybatis的
- 编辑距离
- JDBC
- 浏览器与服务端的通信01
- java.lang.IllegalStateException: Context namespace element 'component-scan' and its parser class [or
- extern修饰全局变量正确用法和链接错误的解决方法
- 字符流
- UVA-140 Bandwidth 带宽
- Sorting In All Out
- Junit
- 字典树
- 句子相似度计算的几种方法