Python教程 - 12网络编程【完结】

更好的阅读体验:点这里www.foooor.com

12 网络编程

我们要在两个应用程序之间进行网络通信,需要使用套接字socket来实现。

socket由IP地址和端口号组成。IP地址用来确定是哪台设备,端口号用来确定是设备上的哪个程序。

在网络编程中,TCP和UDP是两个常用的协议,而socket是在应用层和传输层之间的接口,用于方便地使用TCP或UDP进行网络通信。

TCP和UDP协议的区别:

TCP是一种可靠的面向连接的协议,它在传输数据之前先建立一个连接,确保数据的可靠性和完整性,然后再进行数据传输。

UDP是一种不可靠的无连接协议,它直接将数据分组发送到目的地址,不需要建立连接,速度快,但数据传输的可靠性较差。

12.1 TCP通信

TCP通信是区分服务端和客户端的,服务器启动服务,指定IP和端口,等待客户端的连接。

客户端创建连接,指定服务端的IP和端口,连接到服务端,这样服务端和客户端就可以发送数据了。

1 编写服务端

1、创建socket套接字

import socket

# 1、创建TCP套接字
server_socket = socket.socket()

上面在创建socket的时候,没有明确指定参数,则使用的就是TCP的协议。也可以明确指定使用TCP’协议:

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

``socket.AF_INET 表示使用 IPv4 地址族,socket.SOCK_STREAM` 表示使用 TCP 协议。

2、绑定套接字到本地地址和端口

server_socket.bind(('localhost', 8888))

端口可以自己选择,不要使用已经被使用的端口。

3、监听端口

server_socket.listen(5)
参数为允许连接的客户端数量,超出数量,客户端连接需要等待其他的客户端断开连接

4、等待客户端连接

client_socket, addr = server_socket.accept()

accept()方法是阻塞的,代码运行到这里会一直等待客户端的连接。accept()方法返回的是一个二元元组。

5、从客户端接收数据

ata = client_socket.recv(1024).decode('utf-8')

recv()方法时候读取客户端发送的内容,该方法是阻塞的,会一直等待客户端发送数据。参数指定的是缓冲区的大小。读取到数据后,通过 decode 方法对数据进行解码。

6、服务器发送数据给客户端

服务器也可以通过客户端的连接给客户端发送数据

client_socket.sendall('Hello, World!'.encode('utf-8'))

7、关闭客户端连接

client_socket.close()

8、关闭服务端socket

如果要退出程序,停止接收客户端的连接,则需要关闭服务器端的socket。

server_socket.close()

完整代码:

首先创建一个模块,例如tcp_server.py

import socket

# 1、创建TCP套接字
server_socket = socket.socket()

# 2、绑定套接字到本地地址和端口号
server_socket.bind(('localhost', 8888))

# 3、开始监听连接,参数为允许连接的客户端数量,超出数量,客户端连接需要等待其他的客户端断开连接
server_socket.listen(5)

# 4、等待客户端连接,accept方法是阻塞的,程序运行到这里,会一直等待客户端的连接
client_socket, addr = server_socket.accept()
print('客户端已连接:', addr)

while True:
    # 5、从客户端接收数据
    data = client_socket.recv(1024).decode('utf-8')
    print("接收到客户端的数据:", data)

    # 6、向客户端发送响应
    client_socket.sendall(f"响应:{data}".encode('utf-8'))
    
    if data == "exit":
        break

# 7、关闭客户端连接
client_socket.close()
# 8、关闭服务端socket
server_socket.close()

上面用了while循环,一直循环读取客户端发送的消息,当读取到exit时,退出。

2 编写客户端

1、创建socket套接字

import socket

# 1、创建TCP套接字
client_socket = socket.socket()

2、连接到服务器

client_sock.connect(('localhost', 8888))

指定要连接的服务端的IP和端口,需要和服务端监听的端口一致。

3、向服务端发送数据

client_sock.sendall("要发送的数据".encode('utf-8'))

4、接收服务端的数据

data = client_sock.recv(1024).decode("UTF-8")

5、关闭连接

如果要断开连接,则关闭连接。

client_sock.close()

完整代码:

再创建一个客户端模块,例如tcp_client.py

import socket

# 创建TCP套接字
client_sock = socket.socket()

# 连接到远程服务器
client_sock.connect(('localhost', 8888))

while True:

    # 这里从键盘接收数据
    msg = input("请输入:")

    # 向服务器发送数据
    client_sock.sendall(msg.encode('utf-8'))

    # 接收服务器响应
    data = client_sock.recv(1024).decode("UTF-8")

    # 处理响应数据
    print("服务端:", data)

    if msg == "exit":
        break


# 关闭连接
client_sock.close()

上面使用了一个 while 循环,主要是为了可以不停的通过键盘输入,向服务端发送数据。

当输入 exit 的时候,可以退出程序。

在运行的时候,我们先运行 tcp_server.py 模块,启动服务端。

然后再运行 tcp_client.py 模块,然后在客户端模块通过键盘输入内容发送到服务端,服务端会响应客户端的数据请求。

3 接收多个客户端连接

上面的服务端只能实收一个客户端的连接,因为只在一个线程中进行的。

如果要服务端接收多个客户端的连接,则需要使用多线程来实现。

import socket
import threading


# 处理客户端请求的函数
def handle_client(client_socket, addr):
    print('客户端已连接:', addr)
    try:

        while True:
            # 从客户端接收数据
            data = client_socket.recv(1024).decode('utf-8')
            print('收到数据:', data)

            # 向客户端发送响应
            client_socket.sendall(data.encode('utf-8'))

            if data == "exit":
                print("跳出循环")
                break

        print("关闭客户端连接")
        # 7、关闭客户端连接
        client_socket.close()

    except socket.error as e:
        print('客户端连接异常:', e)
    finally:
        # 关闭客户端连接
        client_socket.close()
        print('客户端已断开:', addr)

# 创建TCP套接字
sock = socket.socket()

# 绑定套接字到本地地址和端口号
sock.bind(('localhost', 8888))

# 开始监听传入连接
sock.listen(5)

# 循环处理客户端请求
while True:
    # 等待客户端连接
    client_socket, addr = sock.accept()

    # 启动一个新线程处理客户端请求
    client_thread = threading.Thread(target=handle_client, args=(client_socket, addr))
    client_thread.start()


# 8、关闭服务端socket
server_socket.close()

这样就可以接收多个客户端的连接了,每连接一个客户端会开启一个线程。

在运行客户端程序的时候,PyCharm默认一个模块是不能运行多个的,需要修改一下配置。

首先打开 Edit Configurations...

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后勾选 Allow parallel run 选项,这样客户端的 tcp_client.py 就可以运行多个了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

12.2 UDP通信

UDP通信比TCP通信更简单一些。使用UDP协议进行通信不需要建立连接,可以直接发送数据包。

1 编写服务端

创建UDP的 Socket 的时候,需要指定 UDP协议:

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

服务端是不需要等待客户端的连接的,直接接收客户端的数据即可。

完整代码:

import socket

# 1、创建UDP套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 2、绑定地址和端口
server_socket.bind(('localhost', 8888))

while True:
    # 3、接收数据
    data, client_address = server_socket.recvfrom(1024)
    msg = data.decode("utf-8")

    print("接收到数据:", msg, ", from", client_address)

    # 4、发送响应
    server_socket.sendto(msg.encode("utf-8"), client_address)

    if msg == "exit":
        break

# 5、关闭套接字
server_socket.close()

发送数据需要使用 sendto 方法。

上面在接收到 exit 字符串后退出。

2 编写客户端

客户端也不需要连接服务端,只需要在发送数据的时候指定 IP 和端口。

import socket

# 1、创建UDP套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

while True:
    msg = input("请输入:")

    # 2、发送数据,需要指定地址和端口
    client_socket.sendto(msg.encode("utf-8"), ('localhost', 8888))

    # 3、接收响应
    data, server_address = client_socket.recvfrom(1024)

    print("响应:", data.decode("utf-8"), ", from", server_address)

    if msg == "exit":
        break

# 4、关闭套接字
client_socket.close()

发送数据需要使用 sendto 方法。

上面在接收到 exit 字符串后退出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

山石岐渡

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

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

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

打赏作者

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

抵扣说明:

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

余额充值