第四讲实验报告

一.Wireshark实验:HTTP

1.HTTP基本请求与应答

http-ethereal-trace-1文件的HTTP报文中的第一条HTTP分组请求报文如下 

第四讲实验报告_第1张图片

客户端IP地址:192.168.1.102

服务器IP地址:128.119.145.12 

分析报文格式:

(1)请求报文 

请求行: 

方法字段:GET

当浏览器请求一个对象时,使用GET方法,绝大部分HTTP请求报文都用GET方法

URL字段:/ethereal-labs/lab2-1.html

请求对象的标识,表示浏览器正在请求的对象,本例是这个html文件

HTTP版本字段:HTTP/1.1

表示浏览器实现的HTTP版本,本例是1.1版本

首部行:

Host: gaia.cs.umass.edu

指明请求对象所在的主机 

User-Agent: Mozilla-5.0

指明用户代理,即向服务器发送请求的浏览器类型 

Accept:浏览器可接受的MIME类型

Accept-Language: 浏览器可接受的相应的语言种类

Accept-Encoding:  浏览器能够进行解码的数据编码方式

Accept-Charset: 浏览器可接受的字符集(或者说客户机采用的编码格式)

Connection: 告诉服务器,请求完成后,是否保持连接

实体体: 

使用GET方法时实体体为空


(2)响应报文 

第二条HTTP分组的响应报文如下:

第四讲实验报告_第2张图片

初始状态行:

协议版本字段:HTTP/1.1

状态码:404表示请求的文档不在服务器上

相应状态信息:Not Found

首部行:

Date: 服务器产生并发送该响应报文的日期和时间

Server: 产生该响应报文的服务器类型 

Vary: 判断是否可使用缓存 

Accept-Ranges: 表明服务器是否支持指定范围的请求,如bytes表示支持字节请求 

Content-Length: 服务器返回的消息正文的长度

Connection: 回送数据后,是否保持连接

Content-Type: 服务器回送数据的类型 

实体体:

所请求的对象本身 

2.HTTP协议缓存的响应分析 

HTTP报文中与缓存有关的字段:

HTTP 状态码(status code):

200 请求成功,浏览器会把响应回来的信息显示在浏览器端

304 第一次访问一个资源后,浏览器会将该资源缓存到本地;第二次再访问该资源时,如果该资源没有发生改变或失效,那么服务器响应给浏览器 304 状态码,告诉浏览器使用本地缓存的资源

Last-Modified: 表示这个响应资源的最后修改时间。web 服务器在响应请求时,告诉浏览器资源的最后修改时间

If-Modified-Since: 当资源过期时(使用 Cache-Control 标识的 max-age),发现资源具有 Last-Modified 声明,则再次向 WEB 服务器请求时,带上 If-Modified-Since,表示请求时间。WEB 服务器收到请求后发现有 If-Modified-Since 则与被请求资源的最后修改时间进行比对。若最后修改时间较新,说明资源有被改动过,则响应资源内容(写在响应消息包体内),HTTP 200 ;若最后修改时间较旧,说明资源无新修改,则响应 HTTP 304 (无需包体,节省流量),告知浏览器继续使用缓存

http-ethereal-trace-2文件的HTTP报文中的第一条HTTP分组如下

第四讲实验报告_第3张图片

第四讲实验报告_第4张图片

可以看到请求报文没有 If-Modified-Since 字段,其响应报文状态码为200,并且包含请求文件内容,说明没有使用缓存

而第二条分组如下: 

第四讲实验报告_第5张图片

第四讲实验报告_第6张图片

请求报文有 If-Modified-Since 字段,其响应报文状态码为304,相应状态描述为Not Modified,且不包含请求文件内容,说明使用了缓存

3.HTTP协议对长文件的处理 

当客户端请求的HTML文件相当长时,一个 TCP 数据包不能容纳。此时单个 HTTP 响应消息由 TCP 分成几个部分,每个部分包含在单独的 TCP 报文段中

第四讲实验报告_第7张图片

 如上图,该HTTP请求的数据被分成4个TCP报文,编号分别为10,11,13,14

4.对嵌入对象网页处理

共发出了3个GET请求,第一个用于请求顶层的HTML网页,后两个用于请求嵌入的两种图片 

根据时间线可以看出,在第一个GET请求的响应报文到达之前,第二个GET请求已经发出,因此二者是并行的

目标网页的IP地址:128.119.245.12

嵌入图片对象cover.jpg的IP地址:134.241.6.82

5. HTTP认证

本实验中主要对基本认证进行分析,基本认证中的认证相关字段:

(1)服务器响应状态码与状态描述:当服务器响应状态码为 401 时,表明服务器资源需要认证

其状态描述为 Unauthorized,表明未通过认证;当响应200 OK时,表明通过认证,正常响应

(2)当用户提供用户名和密码后,重新提出请求时: Authorization: Basic xxxxxxxxxx

Authorization 字段表明在请求中,提供了需要的认证方式和认证信息(已经经过加密)

第四讲实验报告_第8张图片

如图,第对一次GET的响应状态描述为 Unauthorized

WWW-Authenticate字段的值为Basic realm="eth-students only"

第四讲实验报告_第9张图片

如图,查看 Authorization 字段可知第二次请求的认证方式为Basic,服务器响应状态描述为OK

二.Wireshark实验:SMTP/POP

下图是运行MailClient.py时抓取到的SMTP协议

第四讲实验报告_第10张图片

1.涉及到的SMTP关键字

(1)HELO:发送端的主机名

(2)AUTH LOGIN:身份信息验证 

(3)User:发送者用户名

(4)Pass:发送者密码 

(5)MAIL FROM:发信人

(6)PCRT TO:预期的收信人

(7)DATA:邮件主题 

(8)QUIT:断开与邮件服务器的连接

 2.涉及到的SMTP应答

(1)220:服务就绪

(2)235:身份验证成功

(3)250:请求命令完成

(4)334:等待用户输入验证信息

(5)354:开始邮件输入

3.典型的协议格式 

From: XXXXXX

To: XXXXXX

Subject: XXXXXX

Content-Type: XXXXXX

上述抓包实例如下:

第四讲实验报告_第11张图片

三.编程实验1:Web服务器

(1)WebServer.py(思路见注释)

#import socket module
from socket import *
serverSocket = socket(AF_INET, SOCK_STREAM) 
#准备一个服务端套接字 
serverSocket.bind(('',6789))  #绑定本地地址,设置端口号为6789
serverSocket.listen(1)                 #使套接字进入监听状态,并设置连接队列大小为1
while True:     
    #建立连接 
    print('Ready to serve...')  
    connectionSocket, addr = serverSocket.accept()
    #当监听到客户的连接请求后,服务器就调用accept返回并接收这个连接
    #connectionSocket是accept()接收到一个客户端连接请求后返回的一个新的套接字,它代表了服务端和客户端的连接
    #后面可以用于读取数据以及关闭连接
    try:         
        message = connectionSocket.recv(1024) #获取客户端发送的报文,一次最多接收1024个字节
        filename = message.split()[1]  #这两行是在从报文中获取请求的文件名                      
        f = open(filename[1:])         #去掉第一个符号"/"
        outputdata = f.read()          #读取文件
        #Send one HTTP header line into socket         
        header = ' HTTP/1.1 200 OK\nConnection: close\nContent-Type: text/html\nContent-Length: %d\n\n' % (len(outputdata))
        #创建HTTP响应报文
        connectionSocket.send(header.encode()) #发送响应消息头部内容 
        #将请求文件的内容发送给客户
        for i in range(0, len(outputdata)):
            connectionSocket.send(outputdata[i].encode())
        connectionSocket.close()
    except IOError:
        #如果未找到文件,发送差错报文
        header = ' HTTP/1.1 404 Not Found'
        connectionSocket.send(header.encode())
        #关闭客户端套接字
        connectionSocket.close()         
    serverSocket.close()

(2)HelloWorld.html 

Hello world!

(3)运行结果 

请求 HelloWorld.html 文件

第四讲实验报告_第12张图片

请求不存在的文件 

第四讲实验报告_第13张图片

四.编程实验2:邮件客户端

(2)MailClient.py(思路见注释)

from socket import *
from base64 import *

#邮件内容
subject = "I love computer networks!"
contenttype = "text/plain"
msg = "I love computer networks!"
endmsg = "\r\n.\r\n"

# 选择一个邮件服务器,smtp.163.com:123.126.97.4是网易发送邮箱服务
mailserver = "smtp.163.com"

#发件人邮箱地址和收件人邮箱地址
sender_address = "[email protected]"
receiver_address = "[email protected]"

#发送者的账户和密码
username = b64encode("[email protected]".encode()).decode()
password = b64encode("UCOBVJOQDKYYHLJP".encode()).decode()

# 创建一个用户端套接字并和邮件服务器建立TCP连接,25是SMTP的默认端口号
clientSocket = socket(AF_INET,SOCK_STREAM)
clientSocket.connect((mailserver,25))
recv = clientSocket.recv(1024).decode()
print(recv)
if recv[:3] != '220':
    print('220 reply not received from server.')
#服务器返回状态码220代表已建立TCP连接,服务就绪

#向服务端发送HELO命令并打印服务器的应答信息
heloCommand = 'HELO Alice\r\n'
clientSocket.send(heloCommand.encode())
recv1 = clientSocket.recv(1024).decode()
print(recv1)
if recv1[:3] != '250':
    print('250 reply not received from server.')
#服务器返回状态码250代表请求动作正确完成

#发送AUTH LOGIN命令,开始验证身份
clientSocket.sendall('AUTH LOGIN\r\n'.encode())
recv = clientSocket.recv(1024).decode()
print(recv)
if recv[:3] != '334':
    print('334 reply not received from server.')
#服务器返回状态码334代表等待用户输入验证信息

#发送经base64编码的用户名
clientSocket.sendall((username + '\r\n').encode())
recv = clientSocket.recv(1024).decode()
print(recv)
if (recv[:3] != '334'):
	print('334 reply not received from server')
#服务器返回状态码334代表等待用户输入验证信息

#发送经base64编码的密码
clientSocket.sendall((password + '\r\n').encode())
recv = clientSocket.recv(1024).decode()
print(recv)
if (recv[:3] != '235'):
	print('235 reply not received from server')
#服务器返回状态码235代表验证成功

#发送MAIL FROM命令,包含发件人的邮箱地址
clientSocket.sendall(('MAIL FROM: <' + sender_address + '>\r\n').encode())
recv = clientSocket.recv(1024).decode()
print(recv)
if (recv[:3] != '250'):
	print('250 reply not received from server')
#服务器返回状态码250代表请求动作正确完成

#发送RCPT TO命令,包含收件人的邮箱地址
clientSocket.sendall(('RCPT TO: <' + receiver_address + '>\r\n').encode())
recv = clientSocket.recv(1024).decode()
print(recv)
if (recv[:3] != '250'):
	print('250 reply not received from server')
#服务器返回状态码250代表请求动作正确完成

#发送DATA命令,表示即将开始发送邮件内容
clientSocket.send('DATA\r\n'.encode())
recv = clientSocket.recv(1024).decode()
print(recv)
if (recv[:3] != '354'):
	print('354 reply not received from server')
#服务器返回状态码354代表开始邮件输入,以"."结束

#发送邮件内容
message = 'from:' + sender_address + '\r\n'
message += 'to:' + receiver_address + '\r\n'
message += 'subject:' + subject + '\r\n'
message += 'Content-Type:' + contenttype + '\t\n'
message += '\r\n' + msg
clientSocket.sendall(message.encode())
clientSocket.sendall(endmsg.encode())
recv = clientSocket.recv(1024).decode()
print(recv)
if (recv[:3] != '250'):
	print('250 reply not received from server')
#服务器返回状态码250代表请求动作正确完成

#发送QUIT命令断开与邮件服务器的连接
clientSocket.sendall('QUIT\r\n'.encode())

#关闭套接字
clientSocket.close()

(2)运行结果 

第四讲实验报告_第14张图片

第四讲实验报告_第15张图片

第四讲实验报告_第16张图片

你可能感兴趣的:(计算机网络,servlet)