前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >PySide6 GUI 编程(44):异步执行 QRunnable 与 QThreadPool

PySide6 GUI 编程(44):异步执行 QRunnable 与 QThreadPool

原创
作者头像
密码学人CipherHUB
修改于 2024-09-16 08:27:25
修改于 2024-09-16 08:27:25
62100
代码可运行
举报
文章被收录于专栏:编码视界编码视界
运行总次数:0
代码可运行

一个简单的示例

示例代码

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
from __future__ import annotations

import sys
import time
from datetime import datetime

from PySide6.QtCore import Qt, QTimer
from PySide6.QtGui import QFont
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget


def get_time_str() -> str:
    return datetime.now().isoformat(sep = ' ')


def sleep_block() -> None:
    """
    使用 time.sleep(interval) 来暂停程序的执行
    这会导致主线程(即 GUI 线程)被阻塞,无法处理任何其他事件(如更新界面、响应按钮点击等)
    因此,用户在点击按钮后,界面会冻结,直到 sleep 完
    """
    interval = 3
    print('{} begin sleep {}s'.format(get_time_str(), interval))
    time.sleep(interval)
    print('{} end sleep {}s'.format(get_time_str(), interval))


class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Hello, PySide6!')
        self.setToolTip('A PySide6 GUI Application Demo')
        self.setFixedSize(600, 400)

        # 设置计数器
        self.counter = 0
        # 设置定时器,每隔2秒执行一次update_label()方法
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_label)
        self.timer.setInterval(1000)

        # 在窗口中添加标签
        self.label = QLabel(f'{get_time_str()} COUNTER: {self.counter}')
        self.label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.label.setWordWrap(True)
        self.label.setFont(QFont('ComicShannsMono Nerd Font Propo', 25))
        self.label.setStyleSheet("color: green;")

        # 在窗口中添加按钮
        self.button = QPushButton('按下就异常')
        self.button.clicked.connect(sleep_block)

        # 布局
        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.label)
        self.v_layout.addWidget(self.button)
        container = QWidget()
        container.setLayout(self.v_layout)
        self.setCentralWidget(container)

        # 启动定时器
        self.timer.start()

    def update_label(self) -> None:
        self.counter += 1
        self.label.setText(f'{get_time_str()} COUNTER: {self.counter}')


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyMainWindow()
    window.show()
    app.exec()

示例中运行了一个定时器,每隔一秒中计数一次。

当按下按钮时,会触发 sleep_block 进入 sleep 逻辑,这个逻辑会导致主线程卡住,影响界面的交互。

我们可以把按钮按下去后触发的逻辑看作是一个耗时比较久的动作,比如下载资源的过程或者计算的过程,当我们触发了这样的耗时操作后,就会导致整个主界面被卡住。

示例效果

主线程阻塞
主线程阻塞

基于 QRunnable 和 QThreadPool 异步执行耗时逻辑

示例代码

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
from __future__ import annotations

import sys
import threading
import time
from datetime import datetime

from PySide6.QtCore import QRunnable, Qt, QThreadPool, QTimer, Slot
from PySide6.QtGui import QFont
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget


def get_time_str() -> str:
    return datetime.now().isoformat(sep = ' ')


def sleep_block() -> None:
    """
    使用 time.sleep(interval) 来暂停程序的执行
    这会导致主线程(即 GUI 线程)被阻塞,无法处理任何其他事件(如更新界面、响应按钮点击等)
    因此,用户在点击按钮后,界面会冻结,直到 sleep 完
    """
    interval = 3
    print('ID:{}, {} begin sleep {}s'.format(threading.get_ident(), get_time_str(), interval))
    time.sleep(interval)
    print('ID:{}, {} end sleep {}s'.format(threading.get_ident(), get_time_str(), interval))


class BlockWorker(QRunnable):
    def __init__(self):
        super().__init__()

    @Slot()
    def run(self) -> None:
        sleep_block()


class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Hello, PySide6!')
        self.setToolTip('A PySide6 GUI Application Demo')
        self.setFixedSize(600, 400)

        self.threads = QThreadPool()
        print('maximum threads: {}'.format(self.threads.maxThreadCount()))

        # 设置计数器
        self.counter = 0
        # 设置定时器,每隔2秒执行一次update_label()方法
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_label)
        self.timer.setInterval(1000)

        # 在窗口中添加标签
        self.label = QLabel(f'{get_time_str()} COUNTER: {self.counter}\nMAX threads count:{self.threads.maxThreadCount()}')
        self.label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.label.setWordWrap(True)
        self.label.setFont(QFont('ComicShannsMono Nerd Font Propo', 25))
        self.label.setStyleSheet("color: green;")

        # 在窗口中添加按钮
        self.button = QPushButton('开启异步线程')
        self.button.clicked.connect(self.start_threads)

        # 布局
        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.label)
        self.v_layout.addWidget(self.button)
        container = QWidget()
        container.setLayout(self.v_layout)
        self.setCentralWidget(container)

        # 启动定时器
        self.timer.start()

    def update_label(self) -> None:
        self.counter += 1
        self.label.setText(f'{get_time_str()} COUNTER: {self.counter}\nMAX threads count:{self.threads.maxThreadCount()}')

    def start_threads(self) -> None:
        worker = BlockWorker()
        self.threads.start(worker)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyMainWindow()
    window.show()
    app.exec()
实现可异步执行的执行单元
实现可异步执行的执行单元
开启线程
开启线程

示例效果

开启异步线程
开启异步线程

QThreadPool 可以对任意槽函数开启线程

示例代码

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
from __future__ import annotations

import sys
import threading
import time
from datetime import datetime

from PySide6.QtCore import Qt, QThreadPool, QTimer, Slot
from PySide6.QtGui import QFont
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget


def get_time_str() -> str:
    return datetime.now().isoformat(sep = ' ')


class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Hello, PySide6!')
        self.setToolTip('A PySide6 GUI Application Demo')
        self.setFixedSize(600, 400)

        self.threads = QThreadPool()
        print('maximum threads: {}'.format(self.threads.maxThreadCount()))

        # 设置计数器
        self.counter = 0
        # 设置定时器,每隔2秒执行一次update_label()方法
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_label)
        self.timer.setInterval(1000)

        # 在窗口中添加标签
        self.label = QLabel(f'{get_time_str()} COUNTER: {self.counter}\nMAX threads count:{self.threads.maxThreadCount()}')
        self.label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.label.setWordWrap(True)
        self.label.setFont(QFont('ComicShannsMono Nerd Font Propo', 25))
        self.label.setStyleSheet("color: green;")

        # 在窗口中添加按钮
        self.button = QPushButton('开启异步线程')
        self.button.clicked.connect(self.start_threads)

        # 布局
        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.label)
        self.v_layout.addWidget(self.button)
        container = QWidget()
        container.setLayout(self.v_layout)
        self.setCentralWidget(container)

        # 启动定时器
        self.timer.start()

    def update_label(self) -> None:
        self.counter += 1
        self.label.setText(f'{get_time_str()} COUNTER: {self.counter}\nMAX threads count:{self.threads.maxThreadCount()}')

    @Slot()
    def sleep_block(self) -> None:
        """
        for simple use-cases,
        Qt provides a convenience method through QThreadPool.start() which can handle the execution of
        arbitrary Python functions and methods.
        Qt creates the necessary QRunnable objects for you and queues them on the pool.

        QThreadPool.start() 方法可以处理任意的QMainWindow槽函数
        """
        interval = 3
        print('ID:{}, {} begin sleep {}s'.format(threading.get_ident(), get_time_str(), interval))
        time.sleep(interval)
        print('ID:{}, {} end sleep {}s'.format(threading.get_ident(), get_time_str(), interval))

    def start_threads(self) -> None:
        self.threads.start(self.sleep_block)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyMainWindow()
    window.show()
    app.exec()
直接对槽函数开启异步线程
直接对槽函数开启异步线程

示例效果

对槽函数开启异步线程
对槽函数开启异步线程

QThreadPool 对非 QMainWindow 类槽函数生效

示例代码

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
from __future__ import annotations

import sys
import threading
import time
from datetime import datetime

from PySide6.QtCore import Qt, QThreadPool, QTimer, Slot
from PySide6.QtGui import QFont
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget


def get_time_str() -> str:
    return datetime.now().isoformat(sep = ' ')


@Slot()
def sleep_block() -> None:
    """
    如果 sleep_block 函数是一个独立的函数,而不是 MyMainWindow 类的成员方法
    则会导致无法在 start_threads 方法中直接调用 sleep_block
    """
    interval = 3
    print('ID:{}, {} begin sleep {}s'.format(threading.get_ident(), get_time_str(), interval))
    time.sleep(interval)
    print('ID:{}, {} end sleep {}s'.format(threading.get_ident(), get_time_str(), interval))


class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Hello, PySide6!')
        self.setToolTip('A PySide6 GUI Application Demo')
        self.setFixedSize(600, 400)

        self.threads = QThreadPool()
        print('maximum threads: {}'.format(self.threads.maxThreadCount()))

        # 设置计数器
        self.counter = 0
        # 设置定时器,每隔2秒执行一次update_label()方法
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_label)
        self.timer.setInterval(1000)

        # 在窗口中添加标签
        self.label = QLabel(f'{get_time_str()} COUNTER: {self.counter}\nMAX threads count:{self.threads.maxThreadCount()}')
        self.label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.label.setWordWrap(True)
        self.label.setFont(QFont('ComicShannsMono Nerd Font Propo', 25))
        self.label.setStyleSheet("color: green;")

        # 在窗口中添加按钮
        self.button = QPushButton('开启异步线程')
        self.button.clicked.connect(self.start_threads)

        # 布局
        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.label)
        self.v_layout.addWidget(self.button)
        container = QWidget()
        container.setLayout(self.v_layout)
        self.setCentralWidget(container)

        # 启动定时器
        self.timer.start()

    def update_label(self) -> None:
        self.counter += 1
        self.label.setText(f'{get_time_str()} COUNTER: {self.counter}\nMAX threads count:{self.threads.maxThreadCount()}')

    def start_threads(self) -> None:
        self.threads.start(sleep_block)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyMainWindow()
    window.show()
    app.exec()
非 QMainWindow 类槽函数
非 QMainWindow 类槽函数

示例效果

非 QMainWindow 类槽函数正常运行
非 QMainWindow 类槽函数正常运行

为QRunnable类传递参数

示例代码

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
from __future__ import annotations

import sys
import threading
import time
from datetime import datetime
from random import randint

from PySide6.QtCore import QRunnable, Qt, QThreadPool, QTimer, Slot
from PySide6.QtGui import QFont
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget


def get_time_str() -> str:
    return datetime.now().isoformat(sep = ' ')


class MyWorker(QRunnable):
    def __init__(self, *args, **kwargs):
        # 传递参数给 Worker
        super().__init__()
        print('args=', args, 'kwargs=', kwargs)

    @Slot()
    def run(self) -> None:
        print('ID:{}, {} begin sleep 1s'.format(threading.get_ident(), get_time_str()))
        time.sleep(1)
        print('ID:{}, {} end sleep 1s'.format(threading.get_ident(), get_time_str()))


class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Hello, PySide6!')
        self.setToolTip('A PySide6 GUI Application Demo')
        self.setFixedSize(600, 400)

        self.threads = QThreadPool()
        print('maximum threads: {}'.format(self.threads.maxThreadCount()))

        # 设置计数器
        self.counter = 0
        # 设置定时器,每隔2秒执行一次update_label()方法
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_label)
        self.timer.setInterval(1000)

        # 在窗口中添加标签
        self.label = QLabel(f'{get_time_str()} COUNTER: {self.counter}\nMAX threads count:{self.threads.maxThreadCount()}')
        self.label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.label.setWordWrap(True)
        self.label.setFont(QFont('ComicShannsMono Nerd Font Propo', 25))
        self.label.setStyleSheet("color: green;")

        # 在窗口中添加按钮
        self.button = QPushButton('开启异步线程')
        self.button.clicked.connect(self.start_threads)

        # 布局
        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.label)
        self.v_layout.addWidget(self.button)
        container = QWidget()
        container.setLayout(self.v_layout)
        self.setCentralWidget(container)

        # 启动定时器
        self.timer.start()

    def update_label(self) -> None:
        self.counter += 1
        self.label.setText(f'{get_time_str()} COUNTER: {self.counter}\nMAX threads count:{self.threads.maxThreadCount()}')

    def start_threads(self) -> None:
        self.threads.start(
            MyWorker([randint(199, 599) for _ in range(5)], arg1 = 'hello', arg2 = 'pyside6', arg3 = randint(1000, 9999)))


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyMainWindow()
    window.show()
    app.exec()
QRunnable 初始化参数
QRunnable 初始化参数
实例化时传入参数
实例化时传入参数

示例效果

实例化时传入参数
实例化时传入参数

QRunnable发出信号

示例代码

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
from __future__ import annotations

import sys
import threading
import time
from datetime import datetime
from random import randint

from PySide6.QtCore import QObject, QRunnable, Qt, QThreadPool, QTimer, Signal, Slot
from PySide6.QtGui import QFont
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget


def get_time_str() -> str:
    return datetime.now().isoformat(sep = ' ')


class WorkerSignals(QObject):
    begin = Signal(int, str, int)
    finished = Signal(str, str, tuple, dict)


class MyWorker(QRunnable):
    def __init__(self, *args, **kwargs):
        # 传递参数给 Worker
        super().__init__()
        # print('args=', args, 'kwargs=', kwargs)
        # 初始化信号和槽
        self.signals = WorkerSignals()
        self.args = args
        self.kwargs = kwargs

    @Slot()
    def run(self) -> None:
        interval = randint(1, 5)
        # threading.get_ident() 返回的值可能会超过 pyside6中整数的上限值
        # RuntimeWarning: libshiboken: Overflow: Value 5 exceeds limits of type  [signed] "x" (8bytes).
        #   self.signals.finished.emit(threading.get_ident(),
        # 因此这里将 int 转换为 string
        id = threading.get_ident()
        self.signals.begin.emit(str(id),
                                get_time_str(),
                                interval)
        time.sleep(interval)
        self.signals.finished.emit(str(id),
                                   get_time_str(),
                                   self.args,
                                   self.kwargs)


def handle_worker_begin(thread_id: str, time_str: str, interval: int) -> None:
    print('BEGIN thread_id=', thread_id, ', time_str=', time_str, ', sleep {}s'.format(interval))


def handle_worker_finished(thread_id: str, time_str: str, args: tuple, kwargs: dict) -> None:
    print('FINISHED thread_id=', thread_id, ', time_str=', time_str, ', args=', args, ', kwargs=', kwargs)


class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Hello, PySide6!')
        self.setToolTip('A PySide6 GUI Application Demo')
        self.setFixedSize(600, 400)

        self.threads = QThreadPool()
        print('maximum threads: {}'.format(self.threads.maxThreadCount()))

        # 设置计数器
        self.counter = 0
        # 设置定时器,每隔2秒执行一次update_label()方法
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_label)
        self.timer.setInterval(1000)

        # 在窗口中添加标签
        self.label = QLabel(f'{get_time_str()} COUNTER: {self.counter}\nMAX threads count:{self.threads.maxThreadCount()}')
        self.label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.label.setWordWrap(True)
        self.label.setFont(QFont('ComicShannsMono Nerd Font Propo', 25))
        self.label.setStyleSheet("color: green;")

        # 在窗口中添加按钮
        self.button = QPushButton('开启异步线程')
        self.button.clicked.connect(self.start_threads)

        # 布局
        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.label)
        self.v_layout.addWidget(self.button)
        container = QWidget()
        container.setLayout(self.v_layout)
        self.setCentralWidget(container)

        # 启动定时器
        self.timer.start()

    def update_label(self) -> None:
        self.counter += 1
        self.label.setText(f'{get_time_str()} COUNTER: {self.counter}\nMAX threads count:{self.threads.maxThreadCount()}')

    def start_threads(self) -> None:
        worker = MyWorker([randint(9999, 999999) for _ in range(10)],
                          arg1 = 'hello',
                          arg2 = 'world',
                          arg3 = {'a': '1', 'b': 2, 'c': [1, 2, 3, 4, 5, 6]},
                          )
        worker.signals.begin.connect(handle_worker_begin)
        worker.signals.finished.connect(handle_worker_finished)
        self.threads.start(worker)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyMainWindow()
    window.show()
    app.exec()
QRunnable 实例发出信号
QRunnable 实例发出信号
绑定槽函数
绑定槽函数

示例效果

QRunnable 实例通过信号传出数据
QRunnable 实例通过信号传出数据

特别注意

整数溢出问题
整数溢出问题
PySide6 中 int 存在溢出问题,需要转换为 str
PySide6 中 int 存在溢出问题,需要转换为 str
int 转 str 可以规避溢出问题
int 转 str 可以规避溢出问题

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
传输层协议UDP详解
前面已经讲过,HTTP协议是应用层协议,在此之前,我们短暂的认为HTTP是直接通过应用层与外界通信的。但是我们要知道,应用层需要向下将数据传到传输层,再由传输层向下传送。最终才能通过网络传输到接收方。
小灵蛇
2024/10/17
2990
传输层协议UDP详解
【网络编程】十、详解 UDP 协议
​ 在学习 HTTP 等应用层协议时,为了便于理解,可以简单的认为 HTTP 协议是将请求和响应直接发送到了网络当中。但实际应用层需要先将数据交给传输层,再由传输层对数据做进一步处理后再将数据继续向下进行交付,该过程贯穿整个网络协议栈,最终才能将数据发送到网络当中。
利刃大大
2025/05/17
1350
【网络编程】十、详解 UDP 协议
传输层:UDP协议
端口号标识的是一个主机上进行通信的不同的应用程序,通过IP+PORT,便能够确认全网唯一一个进程。
二肥是只大懒蓝猫
2023/10/13
3910
传输层:UDP协议
传输层协议——UDP
ssh服务器, 使用22端口 ftp服务器, 使用21端口 telnet服务器,使用23端口 http服务器, 使用80端口 https服务器, 使用443端口
lovevivi
2023/11/27
2780
传输层协议——UDP
浅谈面向数据报的协议-UDP协议
协议用通俗的话来说就是约定,因为计算机之间的传输媒介是光信号和电信号. 通过 "频率" 和 "强弱" 来表示 0 和 1 这样的信息. 要想传递各种不同的信息, 就需要约定好双方的数据格式.
用户10923087
2024/08/09
2480
浅谈面向数据报的协议-UDP协议
【Linux网络编程】传输协议UDP
TCP/IP 协议中,使用 五元组 (5-tuple) 来唯一标识一条网络通信。这个五元组包含以下五个信息元素:
南桥
2024/12/14
4270
【Linux网络编程】传输协议UDP
【Linux】传输层协议:UDP和TCP
1. 在网络通信中,通信的本质实际就是两台主机上的进程在网络环境中进行通信,也就是数据的传输,而我们总说TCP/IP协议栈,这两个协议分别解决了两个重要的问题,即一台主机如何在网络环境中标定自己的唯一性,一台主机中的某个进程如何在主机内部标定自己的唯一性,实际就是通过网络层协议IP地址和传输层协议端口号port来解决这两个问题的。
举杯邀明月
2023/10/17
1.4K0
【Linux】传输层协议:UDP和TCP
【Linux】深入理解传输层:端口号、UDP协议及其应用场景
端口号(Port)标识了一个主机上进行通信的不同的应用程序。
用户11316056
2024/11/26
5040
【Linux】深入理解传输层:端口号、UDP协议及其应用场景
【Linux网络】网络基础:传输层UDP/TCP协议(一)
前言:传输层协议,特别是用户数据报协议(UDP)和传输控制协议(TCP),是网络通信中最为基础也最为重要的部分。它们不仅决定了数据的传输方式,还影响着数据的可靠性、顺序性和实时性。对于想要深入了解互联网运行机制、掌握网络通信技术的朋友们来说,学习UDP/TCP协议无疑是必经之路。
Eternity._
2024/12/13
1750
【Linux网络】网络基础:传输层UDP/TCP协议(一)
【计算机网络】UDP/TCP 协议
端口号(Port)标识了一个主机上进行通信的不同的应用程序。在 TCP/IP 协议中, 用 “源IP”, “源端口号”, “目的IP”, “目的端口号”, “协议号” 这样一个五元组来标识一个通信(可以通过netstat -n查看)。
YoungMLet
2024/03/16
2570
【计算机网络】UDP/TCP 协议
【Linux】:传输层协议 UDP
🔥 之前在这篇文章 初识网络 中说过关于传输层的内容,以及在 Socket编程应用层UDP 也做过关于 UDP 的练习,如下:
IsLand1314
2025/02/04
5200
【Linux】:传输层协议 UDP
【计网】从零开始掌握序列化 --- 实现网络计算器项目
最重要的是将Socket进行了程序重构,具体的细节在TCP协议中讲解过。这样将通信功能彻底解耦出来:
叫我龙翔
2024/09/25
970
【计网】从零开始掌握序列化 --- 实现网络计算器项目
Linux网络-UDP/TCP协议详解
注:端口号大部分都是16位的,其根本原因就是因为传输层协议当中的端口号就是16位的
用户9645905
2022/11/15
1.8K0
Linux网络-UDP/TCP协议详解
【Linux】TCP网络套接字编程+协议定制+序列化和反序列化
1. 为了让我们的代码更规范化,所以搞出了日志等级分类,常见的日志输出等级有DEBUG NORMAL WARNING ERROR FATAL等,再配合上程序运行的时间,输出的内容等,公司中就是使用日志分类的方式来记录程序的输出,方便程序员找bug。 实际上在系统目录/var/log/messages文件中也记录了Linux系统自己的日志输出,可以看到我的Linux系统中之前在使用时产生了很多的error和warning,我们的代码也可以搞出来这样的输出日志信息到文件的功能。
举杯邀明月
2023/10/17
4660
【Linux】TCP网络套接字编程+协议定制+序列化和反序列化
【Linux】: 传输层协议 TCP
🔥 之前在这篇文章 传输层协议 UDP 中已经说过关于传输层的部分内容,现在我们来了解一下传输层 TCP 的内容吧
IsLand1314
2025/02/20
4130
【Linux】: 传输层协议 TCP
Linux网络UDP与TCP
端口号(Port)标识了一个主机上进行通信的不同的应用程序; 在 TCP/IP 协议中, 用 “源 IP”, “源端口号”, “目的 IP”, “目的端口号”, “协议号” 这样一个五元组来标识一个通信(可以通过 netstat -n 查看);
有礼貌的灰绅士
2025/04/21
2280
Linux网络UDP与TCP
传输层协议TCP详解(上篇)
前面我们已经讲过为什么read、write、recv、send 和 tcp 支持全双工,这其中涉及到发送缓冲区和接收缓冲区(点此查看)。我们创建的TCP套接字,实际上sockfd会指向一个操作系统给分配好的socket file control block(socket文件控制块),而这个socket文件控制块就是维护发送缓冲区和接收缓冲区的。
小灵蛇
2024/10/29
9490
传输层协议TCP详解(上篇)
TCP协议和UDP协议
1.1.2每一条TCP连接只能有两个端点,每一条TCP链接只能是点对点的(一对一)
全栈程序员站长
2022/06/26
1.4K0
TCP协议和UDP协议
初识Linux · 传输层协议UDP
前文我们介绍了UDP的代码使用,流程也是非常简单的,创建了socket,然后填充对应的信息,最后bind,双方就可以进行通信了。通过代码的编写我们发现UDP是简单的,那么我们进入到源码方面学习UDP也是较为简单的。
_lazy
2025/05/08
1360
初识Linux · 传输层协议UDP
【计网】深入理解网络通信:端口号、Socket编程及编程接口
数据传输到主机是目的吗?不是的。因为数据是给人用的。比如:聊天是人在聊天,下载是人在下载,浏览网页是人在浏览!但是人是怎么看到聊天信息的呢?怎么执行下载任务呢?怎么浏览网页信息呢?通过启动的 qq,迅雷,浏览器。 而启动的 qq,迅雷,浏览器都是进程。换句话说,进程是人在系统中的代表,只要把数据给进程,人就相当于就拿到了数据。
用户11316056
2024/11/19
3630
【计网】深入理解网络通信:端口号、Socket编程及编程接口
相关推荐
传输层协议UDP详解
更多 >
LV.0
这个人很懒,什么都没有留下~
目录
  • 一个简单的示例
    • 示例代码
    • 示例效果
  • 基于 QRunnable 和 QThreadPool 异步执行耗时逻辑
    • 示例代码
    • 示例效果
  • QThreadPool 可以对任意槽函数开启线程
    • 示例代码
    • 示例效果
  • QThreadPool 对非 QMainWindow 类槽函数生效
    • 示例代码
    • 示例效果
  • 为QRunnable类传递参数
    • 示例代码
    • 示例效果
  • QRunnable发出信号
    • 示例代码
    • 示例效果
    • 特别注意
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档