文章目录
- 一、初识Socket
- 1.1 什么是 Socket?
- 1.2 socket的基本操作
- 1.3 socket常用函数
- 二、基于UDP实现客户端与服务端通信
- 三、基于TCP实现客户端与服务端通信
- 四、使用requests模块发送http请求
一、初识Socket
1.1 什么是 Socket?
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯
一个生活中的场景。你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。等交流结束,挂断电话结束此次交谈。 生活中的场景就解释了这工作原理,也许TCP/IP协议族就是诞生于生活中,这也不一定
-
在python里面,提供了两个级别访问的网络服务
- 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法
- 高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发
-
通信协议可分为TCP、UDP
- TCP(Transmission Control Protocol传输控制协议)是一种面向连接的,可靠的,基于字节流的传输通信协议
- UDP(User Data Protocol,用户数据报协议)是无连接的,即发送数据之前不需要建立连接,UDP尽最大努力交付,即不保证可靠交付(类似于发短信,我只管发,能不能接受到跟我关系不大)
1.2 socket的基本操作
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。我的理解就是Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)
1.3 socket常用函数
-
创建套接字
- socket.socket(family, type):
- family: 地址族,常用的有 socket.AF_INET(IPv4)和 socket.AF_INET6(IPv6)
- type: 套接字类型,常用的有 socket.SOCK_STREAM(TCP)和 socket.SOCK_DGRAM(UDP)
- socket.socket(family, type):
-
绑定地址
- socket.bind(address):
- address: 一个包含 IP 地址和端口号的元组,用于绑定套接字到指定的地址和端口
- socket.bind(address):
-
监听连接
- socket.listen(backlog):
- backlog: 指定可以排队的最大连接数
- socket.listen(backlog):
-
接受连接
- socket.accept():
- 返回一个新的套接字对象和客户端的地址。这个新的套接字用于与客户端进行通信
- socket.accept():
-
发送和接收数据
- socket.sendall(data):
- data: 要发送的字节数据。确保数据是字节类型(使用 b’…’ 或 str.encode())
- socket.recv(bufsize):
- bufsize: 指定接收数据的最大缓冲区大小。返回接收到的字节数据
- socket.sendall(data):
-
关闭套接字
- socket.close():
- 关闭套接字,释放资源
- socket.close():
-
连接到服务器
- socket.connect(address):
- address: 一个包含服务器 IP 地址和端口号的元组,用于连接到服务器
- socket.connect(address):
二、基于UDP实现客户端与服务端通信
使用socket开发的基本格式
- socket.socket(family,type,proto)
- family: 套接字家族可以使AF_UNIX或者AF_INET
- type: 套接字类型可以根据是面向连接(TCP)的还是非连接分(UDP)为 SOCK_STREAM 或 SOCK_DGRAM
- protocol: 一般不填默认为0
- AF_INET需经过多个协议层的编解码,消耗系统cpu,并且数据传输需要经过网卡,受到网卡带宽的限制。AF_UNIX数据到达内核缓冲区后,由内核根据指定路径名找到接收方socket对应的内核缓冲区,直接将数据拷贝过去,不经过协议层编解码,节省系统cpu,并且不经过网卡,因此不受网卡带宽的限制
- AF_UNIX的传输速率远远大于AF_INET
- AF_INET不仅可以用作本机的跨进程通信,同样的可以用于不同机器之间的通信,其就是为了在不同机器之间进行网络互联传递数据而生。而AF_UNIX则只能用于本机内进程之间的通信
基于UDP开发服务端
UDP 服务器
import socket# 创建一个 UDP 套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 绑定套接字到地址和端口
server_address = ('localhost', 10001)
server_socket.bind(server_address)print('Server is listening on port 10001...')while True:# 接收数据data, client_address = server_socket.recvfrom(1024)print(f'Received from {client_address}: {data.decode()}')# 发送响应server_socket.sendto(b'Echo: ' + data, client_address)
基于UDP开发客户端
import socket# 创建一个 UDP 套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 服务器地址和端口
server_address = ('localhost', 10001)try:# 发送数据message = b'Hello, Server!'client_socket.sendto(message, server_address)# 接收响应response, server_address = client_socket.recvfrom(1024)print(f'Received: {response.decode()}')
finally:# 关闭连接client_socket.close()
三、基于TCP实现客户端与服务端通信
服务端实现
import socket# 创建一个 TCP/IP 套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 绑定套接字到地址和端口
server_address = ('localhost', 10000)
server_socket.bind(server_address)# 监听传入连接
server_socket.listen(5)print('Server is listening on port 10000...')while True:# 等待连接client_socket, client_address = server_socket.accept()print(f'Connection from {client_address}')try:while True:# 接收数据data = client_socket.recv(1024)if not data:breakprint(f'Received: {data.decode()}')# 发送响应client_socket.sendall(b'Echo: ' + data)finally:# 关闭连接client_socket.close()
客户端实现
import socket# 创建一个 TCP/IP 套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 连接到服务器
server_address = ('localhost', 10000)
client_socket.connect(server_address)try:# 发送数据message = b'Hello, Server!'client_socket.sendall(message)# 接收响应response = client_socket.recv(1024)print(f'Received: {response.decode()}')
finally:# 关闭连接client_socket.close()
四、使用requests模块发送http请求
- 安装requests模块
- 使用requests模块发送get请求
import requestsresult = requests.get("https://assets.msn.cn/service/news/feed/pages/channel?InterestIds=Y_ffca5126-f1eb-4232-a09d-0cc253506007&activityId=03B2D6CE-715C-4B69-8691-C0D960DBE69F&apikey=0QfOX3Vn51YCzitbLaRkTTBadtWpgTN8NZLW0C1SEM&cm=zh-cn&it=edgeid&memory=8&ocid=social-peregrine&scn=APP_ANON&timeOut=2000&user=m-20E3F1E5D0826EBF0ABEE2B4D1506FA8")
print(result.content.decode("utf-8"))