标签:
此次是分布式的第三次作业,作业要求如下:
1、基于TCP通讯(ServerSocket、Socket套接字),编写一个带有图形用户界面的浏览器和
一个支持文档读取并返回给客户浏览器的web服务器。客户端支持超链接事件处理,服务器采用多
线程技术支持并发访问。
2、在此基础上,修改服务器侧设计与实现,使之能够动态地添加客户端请求的类文件,即设计
一个小服务程序容器。
3、试在服务器侧代码中对客户端请求行、请求头和请求体部分进行处理。
====================================================================分割线
没有完成第3个要求。
package com.client; import java.io.IOException; public class Client { public static String request; public static void main(String[] args) throws IOException{ Browser browser = new Browser(); //生成浏览器对象 browser.setBrowser(); //调用setBrowser()方法初始化浏览器 } }
package com.client; import java.awt.Button; import java.awt.Frame; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.*; import java.net.Socket; import javax.swing.*; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; @SuppressWarnings("serial") public class Browser extends Frame implements HyperlinkListener { JEditorPane jEditorPane = new JEditorPane();//浏览器显示框 String request = null; //定义字符串保存用户输入的请求 //初始化浏览器框 public void setBrowser() throws IOException { JFrame frame = new JFrame("浏览器"); frame.setSize(800, 600); frame.setLocation(100, 50); frame.setLayout(null); frame.setResizable(false); jEditorPane.setEditable(false); jEditorPane.setContentType("text/html");//设置显示框的文本类型,使可以显示html JScrollPane jScrollPane = new JScrollPane(jEditorPane);//加一个滑动框 jScrollPane.setSize(200, 200); jScrollPane.setLocation(100, 100); jScrollPane.setBounds(50, 100, 700, 450); jEditorPane.addHyperlinkListener(this);//添加超链接监听 TextField textField = new TextField(50); textField.setBounds(200, 50, 320, 30); textField.setText("http://127.0.0.1:8080/");//初始化的时候添加访问地址和端口,不用重复输入 Button button = new Button("前往"); button.setBounds(550, 50, 70, 30); frame.add(textField); frame.add(button); frame.add(jScrollPane); myActionListener myActionListener = new myActionListener(textField); button.addActionListener(myActionListener);//在button上添加监听 //给主frame上添加关闭按钮的功能 frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { // TODO Auto-generated method stub System.exit(0); } }); frame.setVisible(true);//设置可见 } //处理文JEditPane中的超链接 public void hyperlinkUpdate(HyperlinkEvent e){ try{ if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED){ jEditorPane.setPage(e.getURL()); //setPage方法可以直接获取连接内容 } } catch (IOException e1) { e1.printStackTrace(); } } //自定义监听类实现ActionListener接口 class myActionListener implements ActionListener{ TextField textField = new TextField(); //将textField对象传进来,用以取用户的输入内容 public myActionListener(TextField textField) { this.textField = textField;//获取到用户请求的url地址 } //actionPerformed方法用以处理请求 public void actionPerformed(ActionEvent e){ //简单处理请求的url,将其处理成http请求行的样子 String url = textField.getText(); url.trim(); //去掉空格 int beginindex = url.indexOf("//"); url = url.substring(beginindex+2, url.length()); beginindex = url.indexOf("/"); url = url.substring(beginindex, url.length()); request = "POST " + url + " HTTP/1.0\\r\\n"; //设置请求 try { getConnect(); //连接服务器 } catch (IOException e1) { e1.printStackTrace(); } } } public void getConnect() throws IOException{ Socket socket = new Socket("localhost", 8080); //new socket对象访问服务器 socket.setSoTimeout(10000); //设置访问超时的时限,此处设置为10秒 //获取一个输入流和一个输出流,并将两个流都包装起来 OutputStream outputStream = socket.getOutputStream(); PrintWriter socketOutput = new PrintWriter(new OutputStreamWriter(outputStream)); InputStream inputStream = socket.getInputStream(); BufferedReader socketInput = new BufferedReader(new InputStreamReader(inputStream)); //将处理后的用户请求写入输出流,此时的请求格式为http的请求行的格式 socketOutput.println(request);//将用户请求放入输出流中,传送给服务器 socketOutput.flush(); //----以上是处理发送请求到服务器的操作 //----以下是处理服务器反馈的结果 String responseline = new String(); //保存每次从流中取出的信息 String response = new String(); //保存服务器返回的所有信息 responseline = socketInput.readLine(); //从流中读取一行内容 while(responseline != null){ System.out.println(responseline); response = response.concat(responseline); responseline = socketInput.readLine(); } jEditorPane.setText(response); //将服务器返回的内容写入浏览器中 jEditorPane.repaint(); //重画一下浏览器的显示部分 } }
package com.server; import java.io.IOException; public class Server { public static void main(String[] args) throws IOException{ MyServer myserver = new MyServer(); //生成服务器对象 } }
package com.server; import java.io.BufferedReader; import java.io.Closeable; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.net.URL; import javax.servlet.ServletException; //此类实现Runnable接口,以实现多线程功能 public class MyServer implements Runnable { int port = 8080; //定义监听端口 ServerSocket serverSocket = null; //定义一个服务Socket Socket socket = null; //定义一个普通Socket String requestline = null; //定义一个字符串保存用户的请求行 public MyServer() throws IOException{ serverSocket = new ServerSocket(8080); //监听端口8080,参数为端口号 System.out.println("Server服务已经启动。。。。"); //while死循环监听请求,用线程去处理请求 while(true){ socket = serverSocket.accept(); Thread thread = new Thread(this); //将当前对象作为线程参数 thread.start(); //启动线程,执行run()方法 } } //重写run()方法 public void run(){ //定义一个输出流和一个输入流 InputStream inputStream = null; OutputStream outputStream = null; try { inputStream = socket.getInputStream(); //获取输入流 outputStream = socket.getOutputStream(); //获取输出流 //通过Request的构造方法,将输入流传入,然后通过getUri就可以获取用户的请求,并会返回处理后的请求 Request clientrequset = new Request(inputStream); //生成Request对象,将此流传入 requestline = clientrequset.getUri(); //调用getUri方法获取请求行中的路径 //判断是请求页面还是请求servlet if(requestline.startsWith("servlets/")){ //如果是servlets请求,先将输入流传给Response对象 Response responseservlet = new Response(outputStream); //此处生成servlet容器对象,用来处理servlet程序,需要将请求的内容传给servlet容器 ServletCon servletCon = new ServletCon(requestline); try { //通过processServletRequest()方法处理用户请求,需要一个Request对象,和一个Response对象 servletCon.processServletRequest(clientrequset, responseservlet); } catch (ServletException e) { e.printStackTrace(); } System.out.println("处理servlet"); } else{ //如果是请求页面的话,将请求的内容通过setRequest()方法传给Response对象 Response responsehtml = new Response(outputStream);//生成一个Response对象,并将输出流传入 responsehtml.setRequest(requestline); //将请求对象传入 responsehtml.sendStaticResource(); //通过sendStaticResourct()方法将请求的页面返回给客户端 System.out.println("处理html"); } } catch (IOException e) { e.printStackTrace(); } } }
package com.server; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.security.Principal; import java.util.Enumeration; import java.util.Locale; import java.util.Map; import javax.servlet.RequestDispatcher; import javax.servlet.ServletInputStream; import javax.servlet.ServletRequest; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; public class Request implements ServletRequest{ InputStream inputStream = null; //定义一个输入流,用来接收socket输入流的引用 public static String clientrequest = new String(); //保存用户请求行 public Request(InputStream input) { this.inputStream = input; //获取输入流 } //获取用户请求行中的uri标识 public String getUri(){ String requestString = new String(); //保存uri try{ BufferedReader socketInput = new BufferedReader(new InputStreamReader(inputStream)); requestString = socketInput.readLine();//读取用户请求行,保存在requestString中 clientrequest = requestString; //此处需要赋值一次,因为在Servlet程序中要用到 requestString = this.parseUri(requestString); //调用parseUri处理用户请求行 }catch(Exception e){ e.printStackTrace(); } return requestString; //将uri返回,用作比较 } //处理用户请求行 private String parseUri(String requestString){ int beginindex = requestString.indexOf(" "); int endindex = requestString.lastIndexOf(" "); //因为请求行中的资源标识符在两个空格之间,所以取到两个空格的索引 //取出资源定位符 requestString = requestString.substring(beginindex+2, endindex); return requestString; //将定位符返回 } ... }
package com.server; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.Locale; import javax.servlet.ServletOutputStream; import javax.servlet.ServletResponse; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Response implements ServletResponse{ String requestline; //定义请求行字符串,用来保存用户请求 OutputStream output = null; //定义一个输出流 //通过构造方法 ,获取到输出流 public Response(OutputStream output){ this.output = output; } //处理客户的静态页面请求 public void sendStaticResource() throws IOException{ File responsehtml = new File(requestline); //生成用户请求页面对象 //判断文件是否存在 if(responsehtml.exists()){ //存在的话,读取文件中的内容,并放到输出流中 FileReader fileReader = new FileReader(responsehtml); PrintWriter socketOutput = this.getWriter(); //读取文件内容,并写入输出流 int i; while((i = fileReader.read()) != -1){ socketOutput.print((char)i); //转换成char型 } socketOutput.close(); //关闭输出流 }else{ //如果不存在,则输出404 PrintWriter socketOutput = this.getWriter(); socketOutput.println("404 NotFound"); socketOutput.close(); //关闭输出流 } } //获取请求行 public void setRequest(String requestline){ this.requestline = requestline;//获取到Request对象 } //重写此方法 public PrintWriter getWriter() throws IOException { return new PrintWriter(new OutputStreamWriter(output)); } ... }
package com.server; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import javax.servlet.Servlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletCon { ServletRequest request; ServletResponse response; String requestline; //通过构造方法获取到用户请求的内容 public ServletCon(String requestline) { this.requestline = requestline; } //处理servlet请求 public void processServletRequest(Request request, Response response) throws ServletException, IOException{ this.request = request; //获取到Request对象 this.response = response; //获取到Response对象 String servletname = getServletName(requestline); //通过getServletName()方法获取到用户请求的类名 Servlet servlet = loadServlet(servletname); //通过类名获取到对象的servlet程序 servlet.service(request, response); //执行servlet的service方法 } //通过servletname导入servlet程序 private Servlet loadServlet(String servletname) throws ServletException, IOException { //此处的URL要定义到包名之外,不能连报名定义在一块 URLClassLoader loader = new URLClassLoader(new URL[] { new URL("file:E:\\Eclipesworkspace\\fenbushi3\\bin") }); Servlet servlet = null; try { //此处注意在获取类文件的时候需要写全路径,也就是包含包名 Class servletClass = loader.loadClass("com.servlets."+servletname); servlet = (Servlet) servletClass.newInstance(); //实例化一个对象 } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return servlet; } //通过用户的请求行获取到请求的内容 public String getServletName(String requestline){ int beginindex = requestline.indexOf("/"); int endindex = requestline.length(); String servletname = requestline.substring(beginindex+1, endindex); return servletname; } }
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <center> <h1>this is a html page</h1> </center> </body> </html>
package com.servlets; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.server.Request; import com.server.Response; public class MyServlet extends HttpServlet{ //重写service方法 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { Request request = (Request)req; //强制转化成子类对象 String clientrequest = request.clientrequest; //获取到完整请求行 //以下是获取到用户请求方式GET或者是POST int beginindex = 0; int endindex = clientrequest.indexOf(" "); String requestmethod = clientrequest.substring(beginindex, endindex); //System.out.println(requestmethod); //根据不同的请求方式调用不用的方法,默认是POST if(requestmethod.equals("POST")){ doPost(req, res); }else if(requestmethod.equals("GET")){ doGet(req, res); } } //重写doPost方法 protected void doPost(ServletRequest req, ServletResponse res) throws ServletException, IOException { PrintWriter socketOutput = res.getWriter(); //获取到输出流 //输出一句HelloWorld到客户端 socketOutput.println("<h1>"); socketOutput.println("HelloWorld, I am servlet"); socketOutput.println("</h1>"); socketOutput.flush(); //flush一下 socketOutput.close(); //关闭输出流 } protected void doGet(ServletRequest req, ServletResponse res) throws ServletException, IOException { } }
标签:
原文地址:http://blog.csdn.net/u011215133/article/details/51236426