0
点赞
收藏
分享

微信扫一扫

Python 网络编程(三)

彪悍的鼹鼠 2021-09-28 阅读 52

一.TCP流式套接字的应用
1.HTTP网页传输
1)HTTP协议:超文本传输协议,属于应用层协议,应用层协议可以选择传输层服务。
HTTP协议选用的传输层协议是TCP
HTTP协议应用:网页的获取,基于网站的数据传输;也被用作基于HTTP的数据传输
特点:
①应用层协议,传输层使用tcp传输
②简单灵活,和多种语言对接方便
③无状态协议,不记录用户的通信内容
④成熟稳定'http1.1'
工作模式:
①使用HTTP双方均遵循HTTP协议规定发送,接收消息体
②请求方根据协议组织请求内容发送给对方
③服务方,收到内容,按照协议解析
④请求方,收到回复,根据协议解析

2) HTTP请求格式:
请求行 请求头 空行 请求体
①请求行
请求种类 请求内容 协议版本
GET / HTTP/1.1
'请求种类':
GET : 获取网络资源
POST :提交一定的附加数据,得到返回结果
HEAD :获取响应头
PUT : 更新服务器资源
DELETE :删除服务器资源
CONNECT :预留
TRACE :测试
OPTIONS :获取服务器性能
'请求内容:'
浏览器地址栏中IP:端口'/'及'/'之后的内容
备注:浏览器地址栏回车的请求类型:GET
②请求头
以键值对的形式对请求信息进行描述;本阶段学习均采用浏览器自动填充的形式
③请求体
提交具体的请求参数

3) HTTP响应格式:
响应行 响应头 空行 响应体
②响应行:
版本信息 响应码 附加信息
HTTP/1.1 200 OK
响应码:
1xx 请求已接收,正在处理
2xx 请求响应成功
3xx 重定向,完成任务需要其他操作
4xx 客户端错误
5xx 服务端错误

比如:
200 成功
401 没有访问权限
404 请求页面不存在
500 服务器发生未知错误
503 服务器暂时无法执行(可能因为网络原因或者并发量太大导致)
③响应头:
以键值对的形式对响应信息进行具体描述
④响应体:
将客户想要的内容进行返回

代码示例:运行程序,浏览器地址栏输入:127.0.0.1:8000像服务端发起请求;若不存在index.html文件,则触发IOError异常。

'''一个简易的http服务端程序
①响应浏览器http请求
②无论请求什么内容,都响应一个固定的静态页面
注意点:
①connfd.getpeername()获取客户端的IP及端口
②定义响应内容时,响应行,响应头,空行,响应体,用'\r\n'分隔每行内容
③请求字符串可以用splitlines()方法,获得请求行,请求头,空行,请求体组成的列表
'''
import socket
 
def handle_client(connfd):
    '''处理浏览器请求,并返回响应内容'''
    print("Connect to",connfd.getpeername())
    request = connfd.recv(4028).decode()
    requestHeaders = request.splitlines()
    for line in requestHeaders:
        # 打印请求行,请求头,空行及请求体
        print(line)
    try:
        f = open('index.html')
    except IOError:
        response = 'HTTP/1.1 404 not found\r\n' # 响应行
        response += '\r\n' # 空行,响应头选用默认值
        response += '******Sorry the page is not found******' #响应体
    else:
        response = 'HTTP/1.1 200 OK\r\n' # 响应行
        response += '\r\n' # 空行,响应头选用默认值
        # 文件流对象属于可迭代对象,同时也是迭代器
        for i in f:
            response += i #响应体
    finally:
        connfd.send(response.encode())
    connfd.close()    
 
def main():
    sockfd = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    sockfd.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    ADDR = ("0.0.0.0",8000)
    sockfd.bind(ADDR)
    sockfd.listen(5)
    while True:
        print("Waiting for connection...")
        connfd,addr = sockfd.accept()
        #拿到connfd新的套接字后,则立刻交由相应的函数处理浏览器请求
        handle_client(connfd)
    sockfd.close()
 
if __name__ == '__main__':
    main()

2.文件传输
1)服务端

'''文件服务器,发送文件给客户端'''
import socket
 
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 便于调试,设置套接字属性在服务端退出后,短时间恢复,端口可以立即被重用
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
 
ADDR = ("127.0.0.1",8888)
s.bind(ADDR)
s.listen(5)
 
while True:
    print("Waiting for connected...")
    connfd,addr = s.accept()
    print("Connect to",addr)
    # 由客户端指定要下载的文件
    file = connfd.recv(1024)
    with open(file,'rb') as f:
        while True:
            # 循环读取文件内容并发送
            data = f.read(1024)
            if not data:
                break
            connfd.send(data) #以二进制形式打开文件,读取的也是字节流
        connfd.close()
 
s.close()

2)客户端

'''实现从服务器下载文件'''
import socket
 
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ADDR = ("127.0.0.1",8888)
# 向服务端发起连接请求
s.connect(ADDR)
 
# 输入服务端文件
src_file = input("Enter the file name you need:")
# 输入下载保存路径+文件名
des_file = input("Save to file as ?")
if des_file == '':
    des_file = '自定义一个路径' + src_file
else:
    des_file = '自定义一个路径' + des_file
 
s.send(src_file.encode())
 
with open(des_file,'wb') as des:
    while True:
        # 循环接收文件内容,并写入客户端文件
        data = s.recv(1024)
        if not data:
            break
        des.write(data)
 
s.close()

二.UDP数据报套接字的应用

局域网内发送和接收广播消息

1)发送端

'''发送广播消息的目标IP
sendto--->***.***.***.255
'''
import socket
from time import sleep
 
# 创建数据报套接字
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 设置套接字属性:允许接收和发送广播消息
s.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)
 
ADDR = ("广播地址",8888)
 
while True:
    try:
        data = b"This is a broadcast news!"
        # 发送广播消息
        s.sendto(data,ADDR)
        sleep(2)
    except KeyboardInterrupt:
        # Ctrl + C退出
        print("停止广播")
        break
 
s.close()

2)接收端

'''需要能够接收局域网内所有主机的广播消息
绑定IP为"0.0.0.0"
'''
import socket
 
# 创建数据报套接字
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 设置套接字属性:允许接收和发送广播消息
s.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)
 
# 作为接收方,需要绑定IP地址
ADDR = ("0.0.0.0",8888)
s.bind(ADDR)
 
while True:
    try:
        # 接收广播消息
        data,addr = s.recvfrom(1024)
        print("Receive {} from {}".format(data.decode(),addr))
    except KeyboardInterrupt:
        # Ctrl + C退出
        print('停止接收广播消息!')
        break
    except Exception as e:
        print(e)
 
s.close() 
举报

相关推荐

0 条评论