当前位置: 首页 > article >正文

python编写Socket程序

文章目录

  • 编写非阻塞的TCP连接程序
  • 编写UDP的socket程序
    • 创建连接
    • 发送数据
  • 多线程管理udp

编写非阻塞的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()



http://www.kler.cn/a/517525.html

相关文章:

  • 编码器和扩散模型
  • 网络知识小科普--5
  • 微服务搭建----springboot接入Nacos2.x
  • 检测到联想鼠标自动调出运行窗口,鼠标自己作为键盘操作
  • Vue3组件重构实战:从Geeker-Admin拆解DataTable的最佳实践
  • git远程仓库如何修改
  • vue3表格数据分2个表格序号连续展示
  • 基于亿坊PHP框架构建物联网解决方案的优势分析!
  • 【QT】- QThread类介绍和线程的创建
  • 「 机器人 」扑翼飞行器的数据驱动建模核心方法
  • Django基础之ORM
  • arm-linux平台、rk3288 SDL移植
  • (算法竞赛)使用广度优先搜索(BFS)解决迷宫最短路径问题
  • 14.杂谈:领域知识库与知识图谱:概念、关系与重要性
  • 虚拟头节点和双指针解决链表问题(合并,与分解操作,力扣题目为例)
  • 微信小程序date picker的一些说明
  • C++实现设计模式---职责链模式 (Chain of Responsibility)
  • Python结构
  • CMake函数参数
  • 前端【8】HTML+CSS+javascript实战项目----实现一个简单的待办事项列表 (To-Do List)
  • MUSE: PARALLEL MULTI-SCALE ATTENTION FOR SEQUENCE TO SEQUENCE LEARNING 笔记
  • Go语言中变量在栈和堆上分配情况分析
  • 论文:深度可分离神经网络存内计算处理芯片
  • [MySQL]数据库表内容的增删查改操作大全
  • Word 中实现方框内点击自动打 √ ☑
  • -bash: ./uninstall.command: /bin/sh^M: 坏的解释器: 没有那个文件或目录