一、概述

Python 网络编程是指运用 Python 语言编写的网络使用程序。这种编程涉及到网络通讯、套接字编程、协议解析等多种方面的知识。

在 Python 中,有许多内置库和第三方库能够用于网络编程,例如:

  • socket:它是 Python 的内置库,供给了一组简略的套接字 API,能够用于客户端/服务器编程。

  • httplib:它是 Python 的内置库,供给了一组 API,能够用于发送 HTTP 恳求和解析 HTTP 呼应。

  • urllib:它是 Python 的内置库,供给了一组 API,能够用于打开和读取 URL。

  • BeautifulSoup:它是一个第三方库,能够用于解析 HTML 和 XML 文档,便利爬虫编程。

  • Scrapy:它是一个第三方库,供给了一个高档的爬虫框架,能够便利爬虫编程。

运用这些库,能够完成各种类型的网络使用程序,如 Web 使用程序、网络爬虫、网络服务器、客户端/服务器程序等。

Python 高级编程之网络编程 Socket(六)

二、Python socket 模块

Python Socket 编程是 Python 中用于完成客户端/服务器网络通讯的套接字编程。它是 Python 网络编程的基础。

Python 供给了两个基本的 socket 模块。

  • 第一个是 Socket,它供给了标准的 BSD Sockets API。
  • 第二个是 SocketServer, 它供给了服务器中心类,能够简化网络服务器的开发。

1)Socket 类型

套接字格局:

# 运用给定的地址族、套接字类型、协议编号(默以为0)来创立套接字。
socket(family,type[,protocal]) 
socket.AF_UNIX 只能够用于单一的Unix体系进程间通讯
socket.AF_INET 服务器之间网络通讯
socket.AF_INET6 IPv6
socket.SOCK_STREAM 流式socket , for TCP
socket.SOCK_DGRAM 数据报式socket , for UDP
socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW能够;其次,SOCK_RAW也能够处理特别的IPv4报文;此外,利用原始套接字,能够经过IP_HDRINCL套接字选项由用户构造IP头。
socket.SOCK_SEQPACKET 可靠的连续数据包服务

1、创立 TCP Socket

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

示例如下:

import socket
# 创立 socket 目标
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 获取本地主机名
host = socket.gethostname()
# 设置端口号
port = 12345
# 绑定端口
tcp_socket.bind((host, port))
# 监听端口
tcp_socket.listen(5)
print(f"服务端已发动,等候客户端衔接......")

以上代码完成了创立一个 TCP socket,并绑定了本地主机名和端口号,监听端口。

2、创立 UDP Socket

s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

示例如下:

import socket
# 创立 socket 目标
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 获取本地主机名
host = socket.gethostname()
# 设置端口号
port = 12345
# 绑定端口
udp_socket.bind((host, port))
print(f"服务端已发动,等候客户端发送数据......")

以上代码完成了创立一个 UDP socket,并绑定了本地主机名和端口号。

2)Socket 函数

留意点:

  • TCP发送数据时,已建立好TCP衔接,所以不需求指定地址。UDP是面向无衔接的, 每次发送要指定是发给谁。
  • 服务端与客户端不能直接发送列表,元组,字典。需求字符串化repr(data)。

1、服务端socket函数

socket函数 描述
s.bind(address) 将套接字绑定到地址, 在AF_INET下,以元组(host,port) 的方法表明地址.
s.listen(backlog) 开始监听TCP传入衔接。backlog指定在回绝衔接之前,操作 体系能够挂起的最大衔接数量。该值至少为1,大部分使用程 序设为5就能够了。
s.accept() 承受TCP衔接并回来(conn,address),其中conn是新的套 接字目标,能够用来接纳和发送数据。address是衔接客户 端的地址。

2、客户端socket函数

socket函数 描述
s.connect(address) 衔接到address处的套接字。一般address的格局为元组(hostname,port),如果衔接犯错,回来socket.error过错。
s.connect_ex(adddress) 功能与connect(address)相同,但是成功回来0,失利回来error的值。

3、公共socket函数

socket函数 描述
s.recv(bufsize[,flag]) 承受TCP套接字的数据。数据以字符串方法回来,bufsize指定要接纳的最大数据量。flag供给有关音讯的其他信息,一般能够疏忽。
s.send(string[,flag]) 发送TCP数据。将string中的数据发送到衔接的套接字。回来值是要 收的最大数据量。flag供给有关消发送的字节数量,该数量可能小于 息的其他信息,一般能够疏忽。
s.sendall(string[,flag]) 完好发送TCP数据。将string中的数据发送到衔接的套接字,但在回来之前会测验发送所有数据。成功回来None,失利则抛出反常。
s.recvfrom(bufsize[.flag]) 承受UDP套接字的数据。与recv()相似,但回来值是(data,address)。其中data是包括接纳数据的字符串,address是发送数据的套接字地址。
s.sendto(string[,flag],address) 发送UDP数据。将数据发送到套接字,address是方法为(ipaddr,port)的元组,指定长途地址。回来值是发送的字节数。
s.close() 关闭套接字。
s.getpeername() 回来衔接套接字的长途地址。回来值一般是元组(ipaddr,port)。
s.getsockname() 回来套接字自己的地址。一般是一个元组(ipaddr,port)
s.setsockopt(level,optname,value) 设置给定套接字选项的值。
s.getsockopt(level,optname[.buflen]) 设置给定套接字选项的值。
s.settimeout(timeout) 设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表明没有超时期。一般,超时期应该在刚创立套接字时设置,由于它们可能用于衔接的操作(如connect())
s.gettimeout() 回来当前超时期的值,单位是秒,如果没有设置超时期,则回来None。
s.fileno() 回来套接字的文件描述符。
s.setblocking(flag) 如果flag为0,则将套接字设为非堵塞形式,否则将套接字设为堵塞形式(默认值)。非堵塞形式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error反常。
s.makefile() 创立一个与该套接字相关连的文件

Python 中的 socket 库供给了一组简略的 API,能够用于创立套接字,衔接到长途服务器,接纳和发送数据等。下面是一个简略的 Python Socket 示例:

import socket
# 创立一个套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 衔接到长途服务器
s.connect(("www.google.com", 80))
# 发送 HTTP 恳求
s.send("GET / HTTP/1.0\r\n\r\n")
# 接纳呼应数据
data = s.recv(4096)
# 关闭套接字
s.close()
# 打印呼应数据
print(data)

三、单工,半双工以及全双工通讯方法的区别

单工,半双工和全双工是通讯技能中的术语,指的是在通讯过程中,两头设备的信息传输方法不同。

  • 单工(单向通讯):只要一端设备能够发送信息,另一端只能接纳信息,两头不能一起发送和接纳信息。

  • 半双工(半双向通讯):两头设备一起能够发送和接纳信息,但不能一起发送。两头各自占有通讯频道,在不同的时间段内交替发送和接纳信息。

  • 全双工(全双向通讯):两头设备一起能够发送和接纳信息,而且能够一起发送。两头设备能够一起占有通讯频道,而且一起进行信息的传输。

不同的通讯方法适用于不同的场景,例如电话通话归于半双工通讯,而网络数据传输一般归于全双工通讯。在挑选通讯技能时,需求依据详细使用场景,考虑通讯的实践需求,以挑选最合适的通讯方法。

四、单工,半双工以及全双工Python示例

在 Python 中,我们能够运用 socket 模块来完成不同的通讯方法。

1)单工(单向通讯)示例

服务端代码:

import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('0.0.0.0', 8000))
server_socket.listen()
connection, address = server_socket.accept()
print(f'Accepted connection from {address}')
while True:
    data = connection.recv(1024)
    if not data:
        break
    print(f'Received data: {data.decode()}')
connection.close()

客户端代码:

import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 8000))
while True:
    data = input('Enter message to send: ')
    client_socket.sendall(data.encode())
    if data == 'quit':
        break
client_socket.close()

2)半双工(半双向通讯)示例

服务端代码:

import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('0.0.0.0', 8000))
server_socket.listen()
connection, address = server_socket.accept()
print(f'Accepted connection from {address}')
while True:
    data = connection.recv(1024)
    if not data:
        break
    print(f'Received data: {data.decode()}')
    response = input('Enter response: ')
    connection.sendall(response.encode())
    if response == 'quit':
        break
connection.close()

客户端代码:

import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 8000))
while True:
    data = input('Enter message to send: ')
    client_socket.sendall(data.encode())
    if data == 'quit':
        break
    response = client_socket.recv(1024).decode()
    print(f'Received response: {response}')
client_socket.close()

3)全双工(全双向通讯)示例

服务端代码:

import socket
import threading
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('0.0.0.0', 8000))
server_socket.listen()
connection, address = server_socket.accept()
print(f'Accepted connection from {address}')
def receive_data():
    while True:
        data = connection.recv(1024)
        if not data:
            break
        print(f'Received data: {data.decode()}')
def send_data():
    while True:
        data = input('Enter message to send: ')
        connection.sendall(data.encode())
        if data == 'quit':
            break
receive_thread = threading.Thread(target=receive_data)
send_thread = threading.Thread(target=send_data)
receive_thread.start()
send_thread.start()
receive_thread.join()
send_thread.join()
connection.close()

客户端代码:

import socket
import threading
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 8000))
def receive_data():
    while True:
        data = client_socket.recv(1024).decode()
        if not data:
            break
        print(f'Received data: {data}')
def send_data():
    while True:
        data = input('Enter message to send: ')
        client_socket.sendall(data.encode())
        if data == 'quit':
            break
receive_thread = threading.Thread(target=receive_data)
send_thread = threading.Thread(target=send_data)
receive_thread.start()
send_thread.start()
receive_thread.join()
send_thread.join()
client_socket.close()

Python 高档编程之网络编程 Socket讲解就先到这里,有任何疑问欢迎给我留言或私信,后续会持续更新相关技能文章,请小伙伴耐心等候哦,也可关注我的大众号【大数据与云原生技能分享】深入沟通技能~

Python 高级编程之网络编程 Socket(六)