On the shoulders of giants.

Socket 练习题

Web 服务器

你将用 Python 语言开发一个简单的 Web 服务器,它仅能处理一个请求。具体而言,你的 Web 服务器将:

  • 当一个客户(浏览器)联系时创建一个连接套接字;
  • 从这个连接接收 HTTP 请求;
  • 解释该请求以确定所请求的特定文件;
  • 从服务器的文件系统获得请求的文件;
  • 创建一个由请求的文件组成的 HTTP 响应报文,报文前面有首部行;
  • 经 TCP 连接向请求的浏览器发送响应。如果浏览器请求一个在该服务器中不存在的文件,服务器应当返回一个 “404 Not Found” 差错报文。
from socket import *

hostName = ''
hostPort = 2333

# 声明使用 TCP 协议创建欢迎套接字
WEBSocket = socket(AF_INET, SOCK_STREAM)
# 绑定地址(host, port)到套接字
WEBSocket.bind((hostName, hostPort))
# 开始 TCP 监听,操作系统可以挂起的最大连接数量 1 。
WEBSocket.listen(1)
print('Ready Server.')

# 被动接受 TCP 客户端连接,(阻塞式)等待连接的到来
connectionSocket, addr = WEBSocket.accept()
try:
    # 接收TCP数据,bufsize 指定要接收的最大数据量。
    message = connectionSocket.recv(1024)
    filename = message.split()[1]
    f = open(filename[1:].decode('UTF-8'))
    outputdate = f.read()
    # 发送 header 信息
    header = 'HTTP/1.1 200 ok\nConnection: close\nConnent-Type: text/html\nConnent-Length: {}\n\n'
    connectionSocket.send(header.format(len(outputdate)).encode())
    # 发送主体信息
    connectionSocket.send((outputdate.encode()))
    # 关闭套接字
    connectionSocket.close()
except:
    # 未找到文件,则返回 404
    header = 'HTTP/1.1 404 Not Found\n\n'
    connectionSocket.send(header.encode())
    connectionSocket.close()

WEBSocket.close()

UDP ping 程序

你将用 Python 编写一个客户 ping 程序。该客户将发送一个简单的 ping 报文,接收一个从服务器返回的对应 pong 报文,并确定从该客户发送 ping 报文到接收到 pong 报文为止的时延(往返时延,RTT)。我们将创建一个非标准(但简单)的基于 UDP 的 ping 程序。

  • ping 程序经 UDP 向目标服务器发送 10 个 ping 报文;
  • 对每个报文,当对应的 pong 报文返回时,应打印 RTT;
  • 客户等待服务器回答的时间至多为 1 秒;
  • 如果没有收到回答,客户假定该分组丢失并打印相应信息。
# pongServer.py
from socket import *

hostName = ''
hostPort = 2333

serverSocket = socket(AF_INET, SOCK_DGRAM)
serverSocket.bind((hostName, hostPort))

information = 'Hello Client!'

print('Ready Server!')

while True:
	message, addr = serverSocket.recvfrom(1024)
	serverSocket.sendto(information.encode(), addr)

# serverSocket.close()
# pingClient.py
from socket import *
from sys import getsizeof
from time import time

hostName = '192.168.234.130'
hostPort = 2333

pingSocket = socket(AF_INET, SOCK_DGRAM)
pingSocket.settimeout(1)

information = 'Hello Server!'
print('\n正在 Ping {} 具有 {} 字节的数据:'.format(hostName, getsizeof(information)))

for total in range(0, 10):
    try:
        startTime = time()
        pingSocket.sendto(information.encode(), (hostName, hostPort))
        message, addr = pingSocket.recvfrom(1024)
        endTime = time()
        print('来自 %s 的回复: 字节=%d RTT=%fs'
             % (hostName, getsizeof(message), endTime - startTime))
    except:
        print('请求超时!')

pingSocket.close()

邮件客户

创建一个向任何接收方发送电子邮件的简单邮箱客户。你的客户将必须与邮件服务器创建一个 TCP 连接,使用 SMTP 协议与邮件服务器进行交流,经该邮件服务器向某接收方发送一个电子邮件报文,最后关闭与该邮件服务器的 TCP 连接。

import smtplib
from email.mime.text import MIMEText
from email.header import Header
from os import environ

mail_host = 'smtp.qq.com'
mail_user = environ['MAILUSER']
mail_pass = environ['MAILPASS'] # 口令

sender = '319686355@qq.com'
receivers = ['svipvm@yeah.net']

# 构造报文
message = MIMEText('测试 Python Socket 邮件发送!', 'plain', 'utf-8')
message['From'] = Header('VMice', 'utf-8')
message['To'] = Header('SVIPVM', 'utf-8')
subject = '来自一个 SMTP 测试的邮件'
message['Subject'] = Header(subject, 'utf-8')
print(message.as_string())

try:
    smtpObj = smtplib.SMTP()
    smtpObj.connect(mail_host, 25) # 与邮箱服务器连接
    smtpObj.login(mail_user, mail_pass) # 以客户身份登录邮箱
    smtpObj.sendmail(sender, receivers, message.as_string())
    print('Success!')
    smtpObj.quit() # 关闭与邮件服务器连接
except:
    print('ERROR!')

多线程 Web 代理服务器

Share

You may also like...

发表评论

电子邮件地址不会被公开。 必填项已用*标注