浏览器与服务端的通信

服务端代码:

public class WebServer {
    private ServerSocket server;
    /*
     * 线程池,管理用于处理客户端请求的线程
     */
    private ExecutorService threadPool;
    /**
     * 构造方法,用于初始化服务端程序
     * @throws Exception
     */
    public WebServer() throws Exception{
    	try{
    		server=new ServerSocket(8080);
    		threadPool=Executors.newFixedThreadPool(100);
    	}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("服务端启动失败!");
		}
	}
    
}

HttpContent:

/**
 * 定义HTTP协议中的相关信息
 * @author live
 *
 */
public class HttpContent {
	/*
	 * 回车
	 */
	public static final int CR=13;
	/*
	 * 换行
	 */
	public static final int LF=10;
	
}

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();
    		
    		//读取一行字符串,请求行信息
			//Method Request-URI Http-version(CRLF)
			//如:
			//GET/index.html HTTP/1.1CRLF
			//生成HttpRequest表示请求信息
			HttpRequest request=new HttpRequest(in);
			if(request.getUri()!=null){
//    		String line=readline(in);
//    		System.out.println("line:"+line);
//    		if(line.length()>0){
//    			/*
//    			 * 解析Request-URI
//    			 * 1:按照空格拆分请求行
//    			 * 2:取出第二部分
//    			 */
//    			String[] data=line.split("\\s");//空格字符/s
//    			String uri=data[1];
//    			System.out.println("uri:"+uri);
//        		int start=line.indexOf("/");
//        		int end=line.indexOf("H");
//        		String str=line.substring(start+1, end);
//        		System.out.println(str.trim());
    			/*
    			 * 回应客户端对应的资源
    			 * 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
    			 */
    			OutputStream out=socket.getOutputStream();
    		    //响应状态行
    			println("HTTP/1.1 200 OK",out);
    			//发送响应头信息
    			println("Content-Type:text/html",out);
    			//加载客户端需要访问的文件资源
    			File file=new File("webapps"+request.getUri());
    			println("Content-Length:"+file.length(),out);
    			println("",out);//单独发送空行表示响应头发送完毕
    			/*
    			 * 将该文件中所有字节读取出来并发送给客户端
    			 */
    			BufferedInputStream bis=new BufferedInputStream(
    					new FileInputStream(file));
    			int d=-1;
    			while((d=bis.read())!=-1){
    				out.write(d);
    			}
    			bis.close();
    			System.out.println("响应客户端完毕!");
			}
    	   }catch(Exception e){
			e.printStackTrace();
		}finally{
			try{
				socket.close();
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}
	
	/*
	 * 将给定的一行字符串以HTTP协议格式要求按行写出
	 */
	private void println(String str,OutputStream out) 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;
		}
		
	}
	 
}

HttpRequest:

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;
}
  	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值