python 简单网络编程

1. 基础知识

1.1 什么是协议

我理解的协议是数据发送方和接收方相互指定的规则。

1.2 有哪些协议

常用协议
应用层HTTP协议,FTP协议
传输层TCP协议、UDP协议
网络层IP协议、ICMP协议、IGMP协议、ARP协议、RARP协议
网络接口层

TCP传输控制协议(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
UDP用户数据报协议(User Datagram Protocol)是OSl参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。
HTTP超文本传输协议(Hyper Text Transfer Protocol)是互联网上应用最为广泛的一种网络协议。

1.3 分层模型

在这里插入图片描述
TCP/IP模型不是说只有TCP协议和IP协议,在传输层除了TCP外,还可以是UDP协议,此外还包含网络接口层和应用层。
在这里补充一张图:
在这里插入图片描述
这张图中描述了协议模型和所用的协议,其中Samba服务在树莓派与win10主机传输文件方式(未完,占坑)介绍过使用。

1.4 什么是套接字Socket编程

我们编写发出信息的程序和接收信息的程序,并不需要知道信息传输的所有细节,比如 中间经过哪些路由器,路由器之间又是如何传输的。
我们作为程序员,只要知道,我们的程序如何把所要发送的信息交给 ‘收件人’, 如何从 ‘送件人’ 手中获取信息。
那么和我们应用程序直接打交道的 ‘收件人’ 和 ‘送件人’ 到底是谁?
就是操作系统 提供的socket编程接口。

在这里插入图片描述

1.5 套接字通信过程

流式套接字(TCP)
在这里插入图片描述
数据报套接字(UDP)
在这里插入图片描述

2. Python实现

2.1 socket

TCP 服务端程序 server.py

#  === TCP 服务端程序 server.py ===

# 导入socket 库
from socket import *

# 主机地址为空字符串,表示绑定本机所有网络接口ip地址
# 等待客户端来连接
IP = ''
# 端口号
PORT = 50000
# 定义一次从socket缓冲区最多读入512个字节数据
BUFLEN = 512

# 实例化一个socket对象
# 参数 AF_INET 表示该socket网络层使用IP协议
# 参数 SOCK_STREAM 表示该socket传输层使用TCP协议
listenSocket = socket(AF_INET, SOCK_STREAM)

# socket绑定地址和端口
listenSocket.bind((IP, PORT))


# 使socket处于监听状态,等待客户端的连接请求
# 参数 8 表示 最多接受多少个等待连接的客户端
listenSocket.listen(8)
print(f'服务端启动成功,在{PORT}端口等待客户端连接...')

dataSocket, addr = listenSocket.accept()
print('接受一个客户端连接:', addr)

while True:
    # 尝试读取对方发送的消息
    # BUFLEN 指定从接收缓冲里最多读取多少字节
    recved = dataSocket.recv(BUFLEN)

    # 如果返回空bytes,表示对方关闭了连接
    # 退出循环,结束消息收发
    if not recved:
        break

    # 读取的字节数据是bytes类型,需要解码为字符串
    info = recved.decode()
    print(f'收到对方信息: {info}')

    # 发送的数据类型必须是bytes,所以要编码
    dataSocket.send(f'服务端接收到了信息 {info}'.encode())

# 服务端也调用close()关闭socket
dataSocket.close()
listenSocket.close()

下面是TCP 客户端程序 client.py

#  === TCP 客户端程序 client.py ===

from socket import *

IP = '127.0.0.1'
SERVER_PORT = 50000
BUFLEN = 1024

# 实例化一个socket对象,指明协议
dataSocket = socket(AF_INET, SOCK_STREAM)

# 连接服务端socket
dataSocket.connect((IP, SERVER_PORT))

while True:
    # 从终端读入用户输入的字符串
    toSend = input('>>> ')
    if  toSend =='exit':
        break
    # 发送消息,也要编码为 bytes
    dataSocket.send(toSend.encode())

    # 等待接收服务端的消息
    recved = dataSocket.recv(BUFLEN)
    # 如果返回空bytes,表示对方关闭了连接
    if not recved:
        break
    # 打印读取的信息
    print(recved.decode())

dataSocket.close()

2.2 socketserver

socketserver本质是基于socket进行的一个封装,将多线程并发功能集成到一个新的模块里,就叫socketserver;

在原来的socket编程中,有按一定的顺序进行绑定、监听什么的,而socketserver帮助你把这些事情一并完成,你只需要提高IP地址、端口号以及选择适当的协议类型。
关于socketserver模块中各个类,可参考博文Python3之源码解读socketserver工作流程
以下代码摘自:并发编程之socketserver模块(未尝试)
服务器端

import socketserver
class MyTCPhandle(socketserver.BaseRequestHandler):  #必须继承socketserver.BaseRequestHandler这个类
     def handle(self): #必须要实现一个handle方法
         # print(self.request)  #self.request相当于conn
         # print(self.client_address)  #('127.0.0.1', 51393)  self.client_address相当于addr
        while True:
            try:
                data = self.request.recv(1024)  #IO操作
                self.request.send(data.upper())
            except Exception:
                break
        self.request.close()
if __name__ == '__main__':
        server = socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyTCPhandle) #开启线程。accept方法也包括了
         server.allow_reuse_address = True  #默认为False,设为True,相当于 server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) 重用地址
         server.serve_forever() #一直开启,相当于我们以前做的链接循环

客户端

from socket import *
client  = socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))
while True:
    cmd = input('>>:').strip()
     if not cmd:continue
    client.send(cmd.encode('utf-8'))
    data = client.recv(1024)
     print('接受的是:%s'%data.decode('utf-8'))
client.close()

官方说明库:socketserver — 用于网络服务器的框架¶

2.3 http.server

由1.4节中可以知道,socket编程是位于协议和进程之间,主要对象是网络层中的TCP协议,而http.server作用对象则是应用层的http协议。(可能描述不准确)

http.server 使用 socketserver 中的一些类来创建用于实现 HTTP 服务器的基类(基于TCPServer)。HTTPServer 可以直接拿来用,而 BaseHTTPRequestHandler 的目的则是提供一个可供扩展的基础,以便处理各项协议 ( GET,POST 等)。

推荐阅读
Python中的http.server初步使用教程与学习心得 Python3搭建网页
官方文档
3. Python3: 简易的 HTTP 服务器 - http.server
http.server总结
说白了就是利用http.server模块可以创建一个网址,在同一局域网的用户可以查看网址的信息。
为了能够生成相应的网页,必须先遵循相应的HTTP协议,该协议已经封装在http.server的某些类中,因此你需要首先遵循官方文档的写法,创建成功基本的连接。
接下来则需要在网页中添加东西,涉及到"do_GET()",这里也涉及到了HTTP协议相关的内容。

在do_GET()中,如果请求被映射到目录,则会依次检查该目录是否存在 index.html 或 index.htm 文件。若存在则返回文件内容;否则会调用 list_directory() 方法生成目录列表。本方法将利用 os.listdir() 扫描目录,如果 listdir() 失败,则返回 404 出错应答。

在do_GET()函数书写中,设计相应的要求:

     # 1. 发送响应code
       self.send_response(200)

       # 2. 发送响应头
       self.send_header("Content-Type", "text/html; charset=utf-8")
       self.end_headers()

       # 3. 发送响应内容(此处流不需要关闭)
       self.wfile.write("Hello World\n".encode("utf-8"))

参考链接

socket编程

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橙橙小狸猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值