python应用-socket网络编程(1)

本文详细介绍了Python中socket模块的使用,包括服务端和客户端的常用函数,如bind(),listen(),accept(),connect(),send(),recv()等,以及如何通过实例展示客户端和服务端的通信过程,包括创建服务器套接字、客户端连接、数据传输和关闭连接。
摘要由CSDN通过智能技术生成

目录

1 先简单回顾下客户端和服务端通信的知识

2 服务端常用函数

3 客户端常用函数

4 服务端和客户端都用的函数

5 示例介绍客户端和服务端通信过程

6 建立服务端套接制

7 创建服务端函数socket.create_server()

8 创建客户端套接字

9 客户端连接函数socket.create_connection()

10 socket使用with ... as 上下文管理器 

socket 是 Python 标准库中的一个模块,它提供了低级别的网络通信接口。使用 socket 模块,你可以创建客户端和服务器应用程序,以便在网络上进行数据交换。

先简单回顾下客户端和服务端通信的知识

以前我记得面试的时候经常会被问到一个问题:当在浏览器上输入百度域名并回车后,我们能看到浏览器返回了首页的内容,那中间的通信过程是什么?

当然中间经历的过程涉及到了很多通信知识,比如ip地址/tcp协议/http协议/DNS协议等(OSI的七层模型),浏览器的html/js/css等等方方面面,大家可以自行学习。

那要想完成客户端到服务端的tcp连接,首先服务器端要监听ip和port,等待很多个客户端主动发起连接,从而发送数据进行通信。而socket模块的函数就可以支持完成通信过程,我们先介绍下socket的一些常用函数。

服务端常用函数:

bind(address)方法用于将套接字绑定到指定的地址。地址通常是一个包含IP地址和端口号的元组,例如 ('localhost', 80)。

listen(backlog) 方法用于在服务器端套接字上启用监听,等待客户端的连接。backlog 参数指定了最多可以挂起的连接数。

accept() 方法用于接受一个客户端的连接请求,并返回一个新的套接字对象和客户端的地址。这个方法通常用在服务器端,用于处理多个客户端的连接。

客户端常用函数

connect(address) 方法用于客户端连接到指定的服务器地址。地址是一个包含服务器IP地址和端口号的元组。

服务端和客户端都用的函数

send() 和 sendall()

send(bytes) 方法用于发送数据到连接的套接字。sendall(bytes) 方法也是用于发送数据,但它会尝试发送所有数据,直到没有数据需要发送或发生错误。

recv(bufsize, flags=0) 方法用于接收套接字的数据。bufsize 参数指定了要接收的最大字节数。

close()方法用于关闭套接字连接。一旦套接字被关闭,就不能再发送或接收数据。

示例介绍客户端和服务端通信过程

建立服务端套接字

import socket
# 创建一个 socket 对象 基于ipv4和tcp
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定到本地地址和端口
server_address = ('localhost', 8080)
server_socket.bind(server_address)

# 开始监听连接
server_socket.listen(1)
print('Waiting for a connection...')

#接收客户端的连接
connection, client_address = server_socket.accept()
print(f'Connection from {client_address}')

#接收客户端发送的数据
data = connection.recv(1024)
print(f'Received {len(data)} bytes from {client_address}')

#解码2进制内容
if data:
   print(data.decode())
   senddata = data.decode() + ',已收到该消息。'
else:
   senddata = '没有收到消息,等待中'

# 往客户端发送数据
connection.sendall(senddata)

#关闭连接
connection.close()

执行该python程序后:服务端会等待客户端连接:

Waiting for a connection...

创建服务端函数socket.create_server()

python3.9及以上版本提供了socket.create_server() 函数允许快速创建一个套接字并绑定到指定的地址和端口,同时它还可以选择性地监听套接字。这个函数的原型如下:

socket.create_server(address, family=socket.AF_INET, backlog=None, dualstack_ipv6=False)

参数解释:

  • address:一个元组,包含主机地址和端口号,例如 ('localhost', 8000)。
  • family:地址族,默认为 socket.AF_INET(IPv4),也可以使用 socket.AF_INET6(IPv6)。
  • backlog:指定最多连接数,待处理队列的长度。如果未指定或为 None,则使用默认值。
  • dualstack_ipv6:一个布尔值,如果为 True,并且地址族是 socket.AF_INET6,则创建一个双栈套接字,该套接字可以在 IPv4 和 IPv6 之间透明地工作。

以上创建的服务端可以简化:

import socket

server_address = ('localhost', 8080)

#创建服务端socket连接 返回套接字对象
server_socket = socket.create_server(server_address)
print('Waiting for a connection...')

#接收客户端的连接
connection, client_address = server_socket.accept()
print(f'Connection from {client_address}')

#接收客户端发送的数据
data = connection.recv(1024)
print(f'Received {len(data)} bytes from {client_address}')

#解码2进制内容
if data:
   print(data.decode())
   senddata = data.decode() + ',已收到该消息。'
else:
   senddata = '没有收到消息,等待中'

# 往客户端发送数据
connection.sendall(senddata)

#关闭连接
connection.close()

创建客户端套接字

import socket

# 创建一个 socket 对象 基于ipv4和tcp
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接到刚才的服务端的地址和端口
server_address = ('localhost', 8080)
client_socket.connect(server_address)

# 发送数据 往服务端发送数据
message = 'hello world!'
client_socket.sendall(message.encode())

#等待接收服务端发送的数据
data = client_socket.recv(1024)
print(f'Received {len(data)} bytes {data.decode()}')

# 关闭连接
client_socket.close()

执行客户端python程序后,日志打印如下,接收到了服务端发送的内容:

Received 38 bytes hello world!,已收到该消息。

而服务端也收到了客户端发送的内容:

Received 14 bytes from ('127.0.0.1', 51223)

hello world!

客户端连接函数socket.create_connection()

用于简化创建套接字并与服务器建立 TCP 连接的过程。这个函数会创建套接字,尝试连接到指定的地址,并返回连接好的套接字对象。如果连接失败,它会引发一个异常。

socket.create_connection() 的原型如下:

create_connection(address, timeout=None, source_address=None)

参数解释:

  • address:一个包含服务器地址和端口号的元组,例如 ('localhost', 8080)。
  • timeout:可选参数,指定连接超时时间(秒)。如果连接在超时时间内未完成,则抛出异常。默认为 None,表示不设置超时。
  • source_address:可选参数,一个包含源地址和端口号的元组,用于绑定套接字到特定的本地地址和端口。
import socket

# 创建一个 socket 对象 基于ipv4和tcp 连接到刚才的服务端的地址和端口
server_address = ('localhost', 8080)
client_socket=socket.create_connection(server_address)

# 发送数据 往服务端发送数据
message = 'hello world!'
client_socket.sendall(message.encode())

#等待接收服务端发送的数据
data = client_socket.recv(1024)
print(f'Received {len(data)} bytes {data.decode()}')

# 关闭连接
client_socket.close()

socket使用with ... as 上下文管理器

socket这个class支持__enter__() 和__exit__()魔法方法,所以也支持使用with ..as 语句。当程序退出时自动关闭socket连接

import socket
with socket.create_connection(('localhost', 8000)) as sock:
  # 使用 sock 发送和接收数据
  pass # 在这里编写你的代码

共勉: 东汉·班固《汉书·枚乘传》:“泰山之管穿石,单极之绠断干。水非石之钻,索非木之锯,渐靡使之然也。”

-----指水滴不断地滴,可以滴穿石头;

-----比喻坚持不懈,集细微的力量也能成就难能的功劳。

----感谢读者的阅读和学习,谢谢大家。

  • 30
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值