python编写Socket程序

编写非阻塞的TCP连接程序

下面代码使用了select模块来管理多个 socket 连接,server_socket.setblocking(0)将服务器 socket 设置为非阻塞模式 ,在接收数据时,若没有数据可读,会捕获EAGAIN或EWOULDBLOCK错误并继续循环。

import socket
import select


def non_blocking_tcp_server():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_address = ('localhost', 10000)
    server_socket.bind(server_address)
    server_socket.listen(1)
    # 设置为非阻塞模式
    server_socket.setblocking(0)
    inputs = [server_socket]

    print("Server is listening on {}:{}".format(*server_address))

    while inputs:
        readable, writable, exceptional = select.select(inputs, [], inputs)

        for s in readable:
            if s is server_socket:
                connection, client_address = s.accept()
                print(f"New connection from {client_address}")
                connection.setblocking(0)
                inputs.append(connection)
            else:
                try:
                    data = s.recv(1024)
                    if data:
                        print(f"Received from {s.getpeername()}: {data.decode()}")
                        s.sendall(b"Hello, client!")
                    else:
                        print(f"Closing connection from {s.getpeername()}")
                        inputs.remove(s)
                        s.close()
                except socket.error as e:
                    if e.errno in (socket.errno.EAGAIN, socket.errno.EWOULDBLOCK):
                        continue
                    else:
                        print(f"Error: {e}")
                        inputs.remove(s)
                        s.close()

        for s in exceptional:
            print(f"Handling exceptional condition for {s.getpeername()}")
            inputs.remove(s)
            s.close()


if __name__ == "__main__":
    non_blocking_tcp_server()

编写UDP的socket程序

UDP 是无连接的传输协议,相比 TCP 更简单。我将重新编写代码,展示如何使用 Python 实现 UDP 发送和接收报文,重点在于socket模块中 UDP 相关的函数调用。

import socket


def udp_send_receive():
    # 创建UDP socket
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 绑定地址和端口
    server_address = ('localhost', 10001)
    udp_socket.bind(server_address)

    # 发送数据
    message = "Hello, UDP!"
    target_address = ('localhost', 10002)
    udp_socket.sendto(message.encode(), target_address)

    while True:
        try:
            # 接收数据
            data, client_address = udp_socket.recvfrom(1024)
            print(f"Received from {client_address}: {data.decode()}")
        except socket.error as e:
            print(f"Error: {e}")


if __name__ == "__main__":
    udp_send_receive()

上述代码中,先创建 UDP socket 并绑定地址端口,然后向目标地址发送数据,接着进入循环持续接收数据。

这里说明一下UDP的调试,类型选择udp,端口是刚才代码中绑定的端口。

创建连接

在这里插入图片描述
在这里插入图片描述

发送数据

点创建,然后发送随便的内容
在这里插入图片描述
显示收到了数据
在这里插入图片描述

多线程管理udp

下面这个例子,是把收发放在不同的线程中进行运行。提高程序的并发性,我将引入threading模块来创建线程。

import socket
import threading


def udp_send(udp_socket, target_address):
    message = "Hello, UDP!"
    while True:
        try:
            udp_socket.sendto(message.encode(), target_address)
            # 为了避免发送过于频繁,这里添加一个小的时间间隔,单位为秒
            import time
            time.sleep(1)
        except socket.error as e:
            print(f"Send Error: {e}")


def udp_receive(udp_socket):
    while True:
        try:
            data, client_address = udp_socket.recvfrom(1024)
            print(f"Received from {client_address}: {data.decode()}")
        except socket.error as e:
            print(f"Receive Error: {e}")


def main():
    # 创建UDP socket
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 绑定地址和端口
    server_address = ('localhost', 10001)
    udp_socket.bind(server_address)

    target_address = ('localhost', 10002)

    send_thread = threading.Thread(target=udp_send, args=(udp_socket, target_address))
    receive_thread = threading.Thread(target=udp_receive, args=(udp_socket,))

    send_thread.start()
    receive_thread.start()

    send_thread.join()
    receive_thread.join()


if __name__ == "__main__":
    main()


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值