目录

实验三:邮件客户

实验四:多线程Web代理服务器


套接字(socket):可以理解其是在传输层和应用层之间的一个端点(或者一个开口),其形式上是socket = (ip,port),即该通信体的ip和端口号结合为socket,单个socket并不能完整的通信,它是一个端点,还需要通信对等体(peer)的socket,即两个socket连接起来完成通信过程。

实验三:邮件客户

电子邮件邮件系统有三部分组成:用户代理、邮件服务器和简单邮件传输协议(SMTP)。

  • 用户代理允许用户阅读、回复、转发、保存和撰写报文,发信人在用户代理上编辑邮件,并写清楚收件人的邮箱地址;用户代理根据发信人编辑的信息,生成—封符合邮件格式的邮件;用户代理把邮件发送到发信人的的邮件服务器上。
  • 邮件服务器上面有一个缓冲队列,发送到邮件服务器上面的邮件都会加入到缓冲队列中,等待邮件服务器上的客户端进行发送。
  • SMTP协议:简单邮件传输协议(Simple Mail Transfer Protocol,SMTP)是一种提供可靠且有效电子邮件传输的协议,SMTP是建立在FTP文件传输服务上的一种邮件服务。SMTP协议定义了在两个或多个通信实体之间交换的报文的格式和顺序,以及报文发送或报文接收或其他事件采取的动作;即可以一对一发邮件也可以同时一对多发邮件。

实验要求:创建一个向任何接收方发送电子邮件的简单邮件客户:

  1. 你的客户必须与邮件服务器(如谷歌的电子邮件服务器)创建一个TCP连接;
  2. 使用SMTP协议与邮件服务器交谈;
  3. 经该邮件服务器向某接收方(如你的朋友)发送一个电子邮件报文,最后关闭与邮件服务器的TCP连接

从网站获取代码框架并运行:

import smtplib
from email.mime.text import MIMEText
from email.header import Headermail_serve = 'smtp.qq.com'              #确定要建立TCP连接的邮件服务器,这里选qq邮箱
def get_mail_server(sender):            #构建方法筛选出目标邮件地址的名称key = sender[sender.index('@')+1:]  #查找寄信人地址中‘@’标识符并截取@后面内容return "smtp."+key                  #返回smtp格式的邮件服务器地址port = '25'                             #smtp的默认端口号
sender = '257124xxx@qq.com'             #发件人邮箱地址
mail_server = get_mail_server(sender)
sender_pass = 'tcwfibsvyxxxxx'        #授权码,要在邮箱设置中获取授权码,不是登陆密码
receiver = '278120xxx@qq.com'           #收件人邮件地址
mail_msg = 'I make a simple e-mail client!'  #邮件内容# 第一个参数是邮件正文内容
# 第二个是MIME类型,plain是指纯文本内容
# utf-8编码保证多语言兼容性
msg = MIMEText(mail_msg,'plain','utf-8')#建立MIMEText对象
msg['From'] = sender                    #定义发件人From,收信人To,也可以定义主题Subject
msg['To'] = receiver
#msg['Subject'] = Header('SMTP协议作业','utf-8')try:server = smtplib.SMTP(mail_server,port) #通过服务器地址和端口号与邮件服务器建立连接server.login(sender,sender_pass)        #使用授权码登录server.sendmail(sender,(receiver),msg.as_string())  #发送邮件,(receiver)可以发多人因此传入一个list,邮件正文需要一个string类型,利用as_string()把MIMEText对象转为strserver.quit()                           #关闭连接print("邮件发送成功")
except:server.quit()print("邮件发送失败")

运行结果:

我们看抓包过程:筛选端口25(port 25)

(动作1、2)首先看DNS寻址内容:

  • 本机地址——>192.168.31.1(我使用的小米路由器IP):Standard query :smtp.qq.com,请求路由器解析域名smtp.qq.com的IP地址
  • 192.168.31.1——>本机地址:Standard query response:120.241.186.96返回查询到的域名地址

此外从传输协议中可见此次传输使用的是UDP协议。

展开DNS使用UDP和TCP的内容:

DNS设计出来时就同时使用 UDP 和 TCP 协议,对于绝大多数的 DNS 查询来说都会使用 UDP 数据报进行传输,TCP 协议只会在区域传输(它的作用就是在多个命名服务器之间快速迁移记录,由于查询返回的响应比较大,所以会使用 TCP 协议来传输数据包)的场景中使用,其中 UDP 数据包只会传输最大 512 字节的数据,多余的会被截断;DNS 记录中存储的数据会越来越多,同时显示的指出了发现 UDP 包被截断时应该通过 TCP 协议重试。

目前随着使用场景功能的不断扩展,TCP协议来传输不再只是一个重试阶段的协议,它已经作为主要协议来进行使用。

(动作3、4、5)DNS后是TCP协议的客户端和QQ邮箱服务器的三次握手,三次握手建立连接后,开始进行SMTP传输。

看SMTP的传输过程:

SMTP常见指令
HELO(Hello):与服务器确认,通知其客户端使用的机器名称,一般邮件服务器不做限定
MAIL FROM:发件人地址
RCPT TO(Recipient To):收信人的地址
DATA:消息内容

FROM:发信人显示信息

TO:收信人显示信息

SUBJECT:邮件主题
RSET(Reset):传输终止,会话重置
VRFY(Verify):验证用户名或邮箱是否存在,大多数邮箱忽略此命令
NOOP(No operation):让服务器应响应一个OK
QUIT:关闭连接

拓展指令:
EHLO(Extended Hello):标识用户身份
AUTH(Authentication):认证连接
SIZE:消息最大值
HELP:帮助信息

SMTP常见返回码:

220:服务就绪

250:请求动作完成

235:认证通过

221:处理中

354:发送开始,往往与Data指令结合

500:指令错误

550:指令无法完成

(动作6)邮件服务器响应220,建立连接成功,服务就绪:

(动作7)客户端继续发送请求ehlo(或HELO),并在后面附带本机IP地址,即告诉服务器客户端的名称。EHLO和HELO命令的区别在于EHLO带身份验证而HELO不带。

(动作8)服务器使用TCP返回确认收到客户端IP地址的应答。

(动作9)服务器返回250表示请求动作完成,并告诉客户端使用AUTH LOGIN验证方式登录。

(动作10)客户端给服务器发送AUTH LOGIN验证码。

 动作12服务器返回235表示认证通过;动作13客户端请求FROM指令,发送发件人地址;数据传输完成后,动作19服务器返回250 ok;动作20客户端请求rcpt指令,发送收信人地址;动作23客户端请求data指令,准备发送邮件内容;动作25,服务器告知客户端发送开始,并以<CR><LF>.<CR><LF>.结束,客户端收到354响应后开始传输;动作26包含了要发件人、收件人、内容等数据。

动作32传输完成后,服务器返回250 ok queued as,表示请求动作完成,并在排队等候下一个请求;动作33客户端返回quit,表示断开SMTP连接;服务器返回221 bye,表示处理断开连接中。最后客户端发起四次挥手断开TCP连接。

经过简单的分析可以知道,SMTP作为处理邮件传输的协议,它属于明显的请求应答式协议,即一问一答,客户端发送指令,服务器应答,过程中产生的数据传输需要使用数据传输协议TCP或者UDP进行传输。并且从抓包过程中的数据分析,SMTP的传输内容是可以被捕获并可见,因此日常使用SMTP协议还需进行安全保证,如使用SSL协议加密等。

实验四:多线程Web代理服务器

研发一个简单的Web代理服务器,要求:

  • 当你的代理服务器从一个浏览器接收到对某对象的HTTP请求,它生成对相同对象的一个新HTTP请求并向初始服务器发送;
  • 当该代理服务器从初始服务器接收到具有该对象的HTTP响应时,它生成一个包括该对象的新HTTP响应,并发送给该客户;
  • 这个服务器是多相处的,使其在相同时间能处理多个请求。

代理服务器(Proxy Server):大多被用来连接国际互联网和局域网,具有一定的安全功能,比如它可以帮我们不断在互联网上更换IP地址,还可以在数据传输时进行加密;它将我们平时使用网络浏览器直接请求目标服务器的过程分为两步,即客户端先请求代理服务器,由代理服务器去取回客户端的请求内容,然后返回给客户端,这起到了一定的安全防护作用,但无疑增加了许多资源消耗和时间消耗。与此同时,代理服务器也有属于它的缓存区,类似一个大的cache,它不断获取内容缓存在服务器中,当客户端再次请求时,直接传给客户端,节省消耗。

代理服务器也分几种类型,目前流行的有SOCKS代理和HTTP代理;SOCKS代理比传统的HTTP代理更广泛。SOCKS位于传输层上的TCP和UDP(基本上处理所有数据传输的协议)之上。这意味着它可以与客户端和服务器形成物理连接,以尝试确保所有数据包都以与发送相同的方式到达其预期目的地。

但HTTP 和 HTTPS 仍然是最受欢迎的代理。使用 HTTP 代理的主要目的是组织浏览器和其他依赖 TCP 协议的程序的工作。 HTTP 和 HTTPS 代理以非常简单的方式工作。在这种情况下,该程序是浏览器向代理服务器发送打开特定资源 (URL) 的请求。然后,服务器接收数据并将其发送到您的浏览器。HTTP 与 HTTPS 之间的区别在于,前者是非安全代理,而后者是安全代理。

SOCKS 是 Socket Secure 的缩写,是一种网络协议,通过防火墙路由网络流量,从而促进与服务器的通信。 SOCKS 与 HTTP/HTTPS 不同,它不调整 HTTP 标头,服务器将通过自己传输数据而不会更改任何内容。今天,SOCKS 是最先进的数据传输协议,专门为不支持直接使用代理的程序量身定制。 这些是使用标准端口 1080 和 1081 的程序。SOCKS 代理已经从最初的 SOCKS 发展到 SOCKS4 和最新的 SOCKS5。

实验代码(未完善):

from socket import *
import sys
import osif len(sys.argv) <= 1:print('Usage : "python ProxyServer.py server_ip"\n[server_ip : It is the IP Address Of Proxy Server')sys.exit(2)
# Create a server socket, bind it to a port and start listening
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerPort = int(sys.argv[1])
tcpSerSock.bind(("", 8888))            #绑定代理服务器的IP和端口号
print(tcpSerPort)
tcpSerSock.listen(10)
while 1:print('Ready to serve...')         #创建socket连接,接收浏览器传输的数据tcpCliSock, addr = tcpSerSock.accept()print('Received a connection from:', addr)message = tcpCliSock.recv(1024)message = message.decode()print("message:", message)if(message == ''):continue# Extract the filename from the given messageprint("message.split()[1]:", message.split()[1])filename = message.split()[1].partition("/")[2]          #提取请求的文件名print("filename:", filename)fileExist = "false"filetouse = "/" + filenameprint("filetouse:", filetouse)try:                                                    #判断代理服务器缓存是有该文件,有则直接从cache中获取f = open("WEB/" + filetouse[1:], "rb")outputdata = f.read()f.close()fileExist = "true"# ProxyServer finds a cache hit and generates a response messagetcpCliSock.send("HTTP/1.1 200 OK\r\n".encode())      #返回报文和数据tcpCliSock.send("Content-Type:text/html\r\n\r\n".encode())tcpCliSock.send(outputdata)print('Read from cache')# Error handling for file not found in cacheexcept IOError:                                          #从网站请求if fileExist == "false":# Create a socket on the proxyserverc = socket(AF_INET, SOCK_STREAM)hostn = filename.replace("www.","",1)print("hostn:", hostn)try:# Connect to the socket to port 80serverName = hostn.partition("/")[0]#serverName = c.gethostbyname(filename)  serverPort = 80print((serverName, serverPort))c.connect((serverName, serverPort))askFile = ''.join(filename.partition('/')[1:])print("askFile:", askFile)# Create a temporary file on this socket and ask port 80# for the file requested by the clientfileobj = c.makefile('rwb', 0)fileobj.write("GET ".encode() + askFile.encode() + " HTTP/1.0\r\nHost: ".encode() + serverName.encode() + "\r\n\r\n".encode())# Read the response into bufferserverResponse = fileobj.read()# Create a new file in the cache for the requested file.# Also send the response in the buffer to client socket and the corresponding file in the cachefilename = "WEB/" + filenamefilesplit = filename.split('/')for i in range(0, len(filesplit) - 1):if not os.path.exists("/".join(filesplit[0:i+1])):os.makedirs("/".join(filesplit[0:i+1]))tmpFile = open(filename, "wb")print(serverResponse)serverResponse = serverResponse.split(b'\r\n\r\n')[1]print(serverResponse)tmpFile.write(serverResponse)tmpFile.close()tcpCliSock.send("HTTP/1.1 200 OK\r\n".encode())tcpCliSock.send("Content-Type:text/html\r\n\r\n".encode())tcpCliSock.send(serverResponse)except:print("Illegal request")c.close()else:# HTTP response message for file not foundprint("NET ERROR")# Close the client and the server socketstcpCliSock.close()
tcpSerSock.close()

报文和抓包跟实验一的web服务器一致,这是客户端请求代理服务器时,代理服务器将该文件缓存下来的响应过程。

目前存在问题:我还没实现将浏览器请求的非本地文件的部分完善,比如请求域名和其他服务器的文件,一个是将域名通过DNS转为目标IP地址,但我还不会与该服务器建立连接获取文件(会被阻挡反爬虫)这应该类似网络爬虫的内容,我有待学习;第二我还无法在局域网建立一个目标服务器让我连接,来请求文件,这个主要是我只有手上一台电脑。因此本实验进度拖延了!

计算机网络学习——套接字实验(二)相关推荐

  1. 网络编程套接字(二)

    网络编程套接字(二) 文章目录 网络编程套接字(二) 一.简单的UDP网络程序 一.简单的UDP网络程序 封装udp_socket #pragma once #include <cstdio&g ...

  2. 【学习图像处理】之实验二——灰度图像直方图规定化

    灰度图像直方图规定化 图像增强 一.实验内容 二.灰度直方图 1.什么是灰度直方图? 2.直方图均衡化 3.直方图规定化 三.代码实现与分析 0.辅助功能实现 1.绘制原图像直方图SH 2.绘制均衡直 ...

  3. 计算机网络学习④——Cisco Packet Tracer 实验

    Cisco Packet Tracer 实验 本部分实验共有 15 个,需使用 Cisco Packet Tracer 软件完成. 请大家先了解 VLSM.CIDR.RIP.OSPF.VLAN.STP ...

  4. C#中的套接字编程(二) --转

    客户端程序的代码编写:     布置界面.往界面上添加一个ListBox控件(用于显示用户列表),一个RichTextBox控件(用于显示聊天消息以及系统消息),一个 TextBox控件(用于发送消息 ...

  5. 计算机网络自顶向下-套接字编程作业

    作业1:Web服务器 # WebServer.py# import socket module from concurrent.futures import thread from socket im ...

  6. 「计算机网络:自顶向下方法阅读笔记」套接字编程:生成网络应用

    <计算机网络:自顶向下方法>阅读笔记系列 学习套接字编程就是探讨一下网络应用程序是如何实际编写的. 先回顾一下套接字:网络应用是由一对程序(客户程序和服务器程序)组成,位于两个不同的端系统 ...

  7. C#中的套接字编程(一) --转

    TCP/IP 体系结构与特点     TCP/IP协议实际上就是在物理网上的一组完整的网络协议.其中TCP是提供传输层服务,而IP则是提供网络层服务.TCP/IP包括以下协议:     IP:网间协议 ...

  8. TCP/IP网络编程:P1->理解网络编程和套接字

    本系列文章为<TCP/IP网络编程----尹圣雨>学习笔记 文章目录 一.理解网络编程和套接字 1.1 构建接电话套接字 1.2 编写"Hello world!"服务器 ...

  9. Linux·网络编程套接字(三)

    目录 简单的TCP英译汉服务器 简单回顾 更改handler方法 地址转换函数 字符串IP转整数IP 整数IP转字符串IP 绑定失败问题 TCP协议通讯流程 通讯流程总览 三次握手的过程 数据传输的过 ...

最新文章

  1. scala array 删除元素_Array中some介绍
  2. VTK:可视化之VisualizeImageData
  3. 0 win10重装partition_教你在安装WIN10系统中所遇到问题处理方法
  4. python 核心编程 第一部分
  5. overflow-x和文字超出...显示
  6. c# PropertyGrid 自定义属性排序
  7. 如何找到外文文献对应的中文文献?
  8. 计算机win10无法打开小键盘,win10数字小键盘开机不启动解决方法
  9. html逐字显示并停止,Pr字幕如何让他逐字出现逐字消失?
  10. 使用w查看系统负载 vmstat命令 top命令 sar命令 nload命令
  11. android手机打电话时没有网络吗,打电话手机有没有网络 打电话手机有无网络 - 云骑士一键重装系统...
  12. mac 苹果鼠标 magic mouse2 当触摸代替点击当触摸板教程
  13. fork和lockf应用
  14. Daily Reading Time-十月
  15. [Win32] 获取进程完整路径
  16. 长安大学微型计算机原理与接口技术答案,长安大学微机原理与接口技术B卷答案...
  17. eclipse快捷键及各种设置
  18. 阿里云视频云视频增强领域最新研究成果入选国际顶级学术会议
  19. 无聊自己写了个磁力链在线播放app 欢迎大家体验
  20. 网页设计软件dw cc 2019 mac激活方法

热门文章

  1. 学术-几何:黑森错觉
  2. 纯前端实现文件下载功能
  3. 用Python打造属于自己的“今日头条” | 一个非常适合练手的全栈项目
  4. LTE网络有关系统消息(MIB/SIB)深度解析
  5. 小黄的刷题之路(十六)——五行魔法(枚举/蛮力法)
  6. Android AsyncTask 接口回调
  7. 最短路Dijkstra+Floyd
  8. 短视频优质作者必备|配音神器分享|那些你刷视频时肯定听过的声音
  9. 【元器件】芯片封装汇总
  10. matlab 中图字体设置,关于matlab绘图中字体及图片大小等的设置