标签:
此次是分布式的第三次作业,作业要求如下:
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