实验八 应用层网络编程(二)

实验八  应用层网络编程(二)
实验八  应用层网络编程(二)

浙江大学城市学院实验报告

课程名称计算机网络应用

实验项目名称实验八应用层网络编程(二)

实验成绩指导老师(签名)日期2014-06-10

一. 实验目的和要求

1.通过实现使用Java应用层客户端和服务器来获得关于使用Java Socket

网络编程的经验(HTTP)。

二. 实验内容、原理及实验结果与分析

1. HTTP编程(参考电子讲义“网络编程参考资料-应用层.pdf”及教材“第

2章Socket编程”)

阅读“网络编程参考资料-应用层.pdf”中8.3.3部分,实现“HTTP/1.0服务器实现”的源代码(WebServerDemo.java),并在机器上编译运行通过。

设置WEB服务器的发布目录,编写测试网页,并设置端口号,然后通过在命令行中输入相应命令(如“java WebServerDemo d:\src 8001”)启动服务器,在浏览器中进行测试。

【程序源代码】

WebServerDemo.java

import java.io.*;

import https://www.360docs.net/doc/976375558.html,.*;

import java.util.*;

public class WebServerDemo {

// Directory of HTML pages and other files

private String docroot;

// Port number of web server

private int port;

// Socket for the web server

private ServerSocket ss;

// Handler for a HTTP request

// You do not have to make Handler as an inner class.

class Handler extends Thread {

private Socket socket;

private PrintWriter pw;

private BufferedOutputStream bos;

private BufferedReader br;

private File docroot;

public Handler(Socket _socket, String _docroot) throws Exception {

socket=_socket;

// Get the absolute directory of the filepath

docroot=new File(_docroot).getCanonicalFile();

}

public void run() {

try {

// Prepare our readers and writers

br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

bos = new BufferedOutputStream(socket.getOutputStream());

pw = new PrintWriter(new OutputStreamWriter(bos));

// Read HTTP request from user (hopefully GET /file...... )

String line = br.readLine();

// Places the input stream for this socket at "end of stream". Any

// data sent to the input stream side of the socket is acknowledged

// and then silently discarded. If you read from a socket input stream

// after invoking shutdownInput() on the socket, the stream will

// return EOF.

socket.shutdownInput();

if(line == null) {

socket.close();

return;

}

// let's take a look at what the server received

System.out.println(line);

if(line.toUpperCase().startsWith("GET")) {

// Eliminate any trailing ? data, such as for a CGI GET request

StringTokenizer tokens = new StringTokenizer(line," ?");

tokens.nextToken();

String req = tokens.nextToken();

// If a path character / or \ is not present, add it to the // document root

// and then add the file request, to form a full filename

String name;

if(req.startsWith("/") || req.startsWith("\\"))

name = docroot + req;

else

name = docroot + File.separator + req;

// Get absolute file path

File file = new File(name).getCanonicalFile();

// Check to see if request doesn't start with our document root ....

if(!file.getAbsolutePath().startsWith(docroot.getAbsolutePath())) {

pw.println("HTTP/1.0 403 Forbidden");

pw.println();

}

// ... if it's missing .....

else if(!file.exists()) {

pw.println("HTTP/1.0 404 File Not Found");

pw.println();

}

// ... if it can't be read for security reasons ....

else if(!file.canRead()) {

pw.println("HTTP/1.0 403 Forbidden");

pw.println();

}

// ... if its actually a directory, and not a file ....

else if(file.isDirectory()) {

sendDir(bos,pw,file,req);

}

// ... or if it's really a file

else {

sendFile(bos, pw, file.getAbsolutePath());

}

}

// If not a GET request, the server will not support it

else {

pw.println("HTTP/1.0 501 Not Implemented");

}

pw.flush();

bos.flush();

} catch(Exception e) {

e.printStackTrace();

}

try {

socket.close();

} catch(Exception e) {

e.printStackTrace();

}

}

protected void sendFile(BufferedOutputStream bos, PrintWriter pw,

String filename) throws Exception { try {

BufferedInputStream bis = new BufferedInputStream(new

FileInputStream(filename));

byte[] data = new byte[10*1024];

int read = bis.read(data);

pw.println("HTTP/1.0 200 Okay");

pw.println();

pw.flush();

bos.flush();

while(read != -1) {

bos.write(data,0,read);

read = bis.read(data);

}

bos.flush();

} catch(Exception e) {

pw.flush();

bos.flush();

}

}

protected void sendDir(BufferedOutputStream bos, PrintWriter pw,

File dir, String req) throws Exception { try {

pw.println("HTTP/1.0 200 Okay");

pw.flush();

pw.print("Directory of ");</p><p>pw.print(req);</p><p>pw.print("

Directory of ");

pw.print(req);

pw.println("

");

File[] contents=dir.listFiles();

for(int i=0;i

pw.print("

");

pw.print("

");

pw.println("

");

}

pw.println("

pw.print(req);

pw.print(contents[i].getName());

if(contents[i].isDirectory())

pw.print("/");

pw.print("\">");

if(contents[i].isDirectory())

pw.print("Dir -> ");

pw.print(contents[i].getName());

pw.print("

");

pw.flush();

} catch(Exception e) {

pw.flush();

bos.flush();

}

}

}

// Check that a filepath has been specified and a port number

protected void parseParams(String[] args) throws Exception {

switch(args.length) {

case 1:

case 0:

System.err.println ("Syntax: "+this.getClass().getName()+

" docroot port");

System.exit(0);

default:

this.docroot = args[0];

this.port = Integer.parseInt(args[1]);

break;

}

}

public WebServerDemo(String[] args) throws Exception {

System.out.println ("Checking for paramters");

// Check for command line parameters

parseParams(args);

System.out.print ("Starting web server...... ");

// Create a new server socket

ss = new ServerSocket(port);

System.out.println ("OK");

for (;;) {

// Accept a new socket connection from our server socket

Socket accept = ss.accept();

// Start a new handler instance to process the request

new Handler(accept, docroot).start();

}

}

// Start an instance of the web server running

public static void main(String[] args) throws Exception {

WebServerDemo webServerDemo = new WebServerDemo(args); }

}

【实验结果与分析】

2. Ethereal抓包分析

用Ethereal软件截获上面程序运行时客户端和服务器之间发送的数据包,并且根据截获的数据包内容进行分析。

【实验结果与分析】

host 10.66.19.27 and tcp port 8001

TCP数据包结构

下面的表格的值取自图中选中的数据包:

前32位

三次握手的数据包

10.66.19.35 -> 10.66.19.27 [SYN](Seq=0);

10.66.19.27 -> 10.66.19.35 [SYN,ACK](Seq=0,Ack=1);

10.66.19.35 -> 10.66.19.27 [ACK](Seq=1,Ack=1);

三. 讨论、心得

记录实验感受、上机过程中遇到的困难及解决办法、遗留的问题、意见和建议等。

相关主题
相关文档
最新文档