首页 > 编程语言 >Python Socket编程:从原理到实践

Python Socket编程:从原理到实践

时间:2024-06-04 23:29:53浏览次数:26  
标签:UDP Socket Python 编程 sock TCP data socket

在当今的网络世界中,Socket编程是构建网络通信应用的关键技术之一。从简单的聊天应用到复杂的分布式系统,Socket编程都扮演着至关重要的角色。本文将首先介绍Socket编程的基本原理,然后详细讲解如何使用Python进行Socket编程。

注意:文中谈到的TCP/IP协议可以去我另一篇文章看一下,本文主要讲我们怎么进行socket编程。

一、Socket编程原理

Socket编程是一种网络通信的API,它提供了跨平台、跨语言的网络通信能力。Socket编程接口实际上是一个广泛的编程接口,可以用于多种协议,包括TCP、UDP以及其他更底层的协议(如原始套接字用于IP层通信)。但是在大多数应用中,TCP和UDP是最常用的协议(因为它们提供了网络编程所需的基本特性),所以本文主要讲TCP Socket 编程和UDP Socket 编程。

TCP Socket 编程

当我们在使用Socket API进行编程时,我们写的代码实际上是在与TCP/IP协议栈进行交互。

具体流程如下:

  1. 创建Socket:当您创建一个Socket对象时,您实际上是在请求TCP/IP协议栈分配一个唯一的套接字标识符(socket ID)和相关的资源。
  2. 绑定地址:绑定操作告诉TCP/IP协议栈,您希望将哪个IP地址和端口号与您的Socket关联起来。这样,当远程主机尝试连接到您的Socket时,TCP/IP协议栈就知道如何处理这个连接请求。
  3. 监听连接:服务器端Socket的监听操作告诉TCP/IP协议栈,它应该接受来自客户端的连接请求。当有客户端发起连接时,TCP/IP协议栈会处理底层的连接建立过程,并通知您的代码连接已经建立。
  4. 数据交换:当您使用Socket发送或接收数据时,您的代码实际上是在将数据传递给TCP/IP协议栈,或者从TCP/IP协议栈接收数据。TCP/IP协议栈负责将数据打包成适当的格式(例如,TCP数据包或UDP数据报),并将其发送到目标主机。同样,当TCP/IP协议栈接收到来自远程主机的数据时,它会将数据传递给与Socket关联的代码。
  5. 关闭连接:当您关闭Socket连接时,您的代码实际上是在告诉TCP/IP协议栈释放与该连接关联的所有资源。TCP/IP协议栈会负责完成底层的连接关闭过程。

UDP Socket 编程

当使用Socket进行UDP(用户数据报协议)通信时,原理与TCP通信有所不同,因为UDP是一个无连接、不可靠的传输协议。

具体流程如下:

  1. 创建Socket
    在通信的两端(客户端和服务器),都需要创建一个UDP Socket对象。这个对象将负责UDP通信的相关操作。
  2. 绑定地址(可选)
    对于服务器端Socket,通常也需要绑定到一个具体的IP地址和端口号上,以便客户端能够找到它。但需要注意的是,UDP的绑定是可选的,如果服务器端不绑定到特定端口,那么操作系统会为其选择一个可用的临时端口。
    客户端Socket则不需要绑定,因为UDP是无连接的,客户端只需要知道服务器的IP地址和端口号就可以发送数据报。
  3. 发送数据报
    客户端使用UDP Socket的sendto方法向服务器发送数据报。在发送时,需要指定目标服务器的IP地址和端口号。
    服务器使用UDP Socket的recvfrom方法来接收来自客户端的数据报。这个方法会返回发送方的IP地址和端口号,以及接收到的数据内容。
  4. 数据交换
    UDP通信中,数据以数据报的形式发送和接收。每个数据报都是独立的,不依赖于之前的或之后的数据报。
    UDP不提供像TCP那样的流控制、错误检查和顺序保证。这意味着数据报可能会丢失、乱序或重复到达。因此,在UDP通信中,应用程序需要负责处理这些问题。
  5. 关闭连接
    与TCP不同,UDP没有显式的连接建立和关闭过程。当数据报发送或接收完成后,Socket对象通常可以继续使用,或者可以被销毁以释放资源。
  6. 广播和多播
    UDP还支持广播和多播功能。广播是指向本地网络上的所有主机发送数据报,而多播则是向一组特定的主机(属于同一个多播组)发送数据报。这些功能在需要向多个接收者发送相同数据的情况下非常有用。
  7. 缓冲区管理
    UDP Socket有一个接收缓冲区来存储接收到的数据报。如果应用程序没有及时读取接收缓冲区中的数据,那么新的数据报可能会覆盖旧的数据报(取决于缓冲区的大小和配置)。因此,在使用UDP时,应用程序需要确保及时读取接收到的数据报。

二、Python Socket编程实践

Python提供了丰富的Socket编程库,使得开发者可以轻松地实现网络通信功能。

基于TCP协议的Python socket编程

TCP 服务器
import socket


def tcp_server():
    # 创建一个TCP/IP socket
    # 参数 AF_INET 表示该socket网络层使用IP协议
    # 参数 SOCK_STREAM 表示该socket传输层使用TCP协议
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 绑定到地址和端口
    server_address = ('localhost', 12345)
    sock.bind(server_address)

    # 监听连接,等待客户端的连接请求
    # 最多接受2个等待连接的客户端
    sock.listen(2)
    print('等待连接...')
    connection, client_address = sock.accept()
    print(f"接受一个客户端连接 {client_address}")

    # 接收数据并返回
    while True:
        # 指定从接收缓冲里最多读取100个字节
        recv_data = connection.recv(100)   # 返回的数据是bytes类型的,需要用decode()解码
        print(f"收到信息: {recv_data.decode()}")
        if recv_data.decode() == "退出":
            break

        send_data = input("输入发送给客户端的数据: ")
        connection.send(send_data.encode())   # 发送的数据也是bytes类型的,所以这里需要encode()编码
        if send_data == "退出":
            break

    connection.close()
    sock.close()


if __name__ == '__main__':
    tcp_server()
TCP 客户端
import socket


def tcp_client():
    # 创建一个TCP/IP socket
    # 参数 AF_INET 表示该socket网络层使用IP协议
    # 参数 SOCK_STREAM 表示该socket传输层使用TCP协议
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 连接到服务器
    server_address = ('localhost', 12345)
    sock.connect(server_address)

    while True:
        # 发送数据
        # send_data = b'123'
        send_data = input("输入发送的数据: ")
        sock.send(send_data.encode())
        if send_data == "退出":
            break

        # 接收数据
        recv_data = sock.recv(100)
        print(f"接收到的数据 {recv_data.decode()}")
        if recv_data.decode() == "退出":
            break

    sock.close()


if __name__ == '__main__':
    tcp_client()

基于UDP协议的Python socket编程

UDP 服务器
import socket


def udp_server():
    # 创建一个UDP socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 绑定到地址和端口
    server_address = ('localhost', 12345)
    sock.bind(server_address)

    while True:
        # 接收数据
        # print('等待接收数据...')
        recv_data, address = sock.recvfrom(4096)
        print(f"地址: {address} 数据: {recv_data.decode()}")
        if recv_data.decode() == "退出":
            break

        # 发送数据
        send_data = input("请输入要发送的数据: ")
        sent = sock.sendto(send_data.encode(), address)
        print(f"向{address}发送{sent}字节")
        if send_data == "退出":
            break

    sock.close()


if __name__ == '__main__':
    udp_server()
UDP 客户端
import socket


def udp_client():
    # 创建一个UDP socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 服务器地址和端口
    server_address = ('localhost', 12345)

    while True:
        # 发送数据
        # send_data = b'123'  # 这种方式是不能写中文的,所以还是建议用encode()
        send_data = input("请输入要发送的数据: ")
        sent = sock.sendto(send_data.encode(), server_address)

        # 接收数据
        # print('等待接收数据...')
        recv_data, server = sock.recvfrom(4096)
        print(f"地址: {server} 数据: {recv_data.decode()}")
        if recv_data.decode() == "退出":
            break

    sock.close()


if __name__ == '__main__':
    udp_client()

标签:UDP,Socket,Python,编程,sock,TCP,data,socket
From: https://blog.csdn.net/qq_64192931/article/details/139442726

相关文章

  • Python案例
    音乐播放器importtkinterastkimporttkinter.filedialogimportosfrompygameimportmixerclassMusicPlayer:def__init__(self,root):self.root=rootself.root.title("MusicPlayer")self.root.geometry("300x100&......
  • [轨迹规划实操] 横向优化算法+纵向DP算法的python复现(2)
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言纵向速度规划1.对路程和时间进行采样2.计算代价函数3.选出最小代价的点进行回溯4.实验结果前言本文采用基于优化的横向规划方法和基于动态规划的纵向规划方法横向优化控制详见第一......
  • 使用Venv创建Python的虚拟环境
    创建虚拟环境python3-mvenv<directory_name>激活虚拟环境source<directory_name>/bin/active检查当前使用的是哪个Python下面这条命令会输出当前使用Python环境的目录:whichpython配置好之后使用pip安装的库就会默认放在这个环境中停用当前环境deactivate重启环......
  • Python网络爬虫要清理cookies 才能再爬,有啥解决方法嘛?
    大家好,我是Python进阶者。一、前言前几天在Python钻石交流群【大写一个Y】问了一个Python基网络爬虫的问题,问题如下:大佬们请教个问题我做了个在某眼查抓地址数据的爬虫,程序中做了随机2-5秒的循环延时,现在大概爬800多个地址,就会查不出数据,要清理cookies才能再爬,有啥解决方法......
  • c# Socket简单介绍
    1、socket简介在C#中,Socket是一个表示网络套接字的类。套接字是一种在应用程序之间进行通信的接口,可以用来实现基于TCP/IP协议的网络应用程序。Socket类提供了创建、管理和维护网络连接的功能,是.NETFramework中的一个基本网络通信类。Socket类的主要作用是提供了......
  • python学习笔记-04
    高级数据类型一组按照顺序排列的值称为序列,python中存在三种内置的序列类型:字符串、列表和元组。序列可以支持索引和切片的操作,第一个索引值为0表示从左向右找,第一个索引值为负数表示从右找。1.字符串操作1.1切片切片是指选取字符串中的某些数据,语法:字符串[开始下标:结......
  • python系列:一文读懂FastAPI:Python 开发者的福音
    一文读懂FastAPI:Python开发者的福音一文读懂FastAPI:Python开发者的福音第一步:安装FastAPI第二步:创建一个FastAPI应用第三步:定义接口第四步:运行应用第五步:查看接口文档总结一文读懂FastAPI:Python开发者的福音FastAPI是一个基于Python的现代化Web框架,它提供了快......
  • Python用GRU神经网络模型预测比特币价格时间序列数据2案例可视化|附代码数据
    全文链接:https://tecdat.cn/?p=36389原文出处:拓端数据部落公众号门控循环单元(GRU)是一种循环神经网络(RNN)类型,旨在有效地捕获序列数据中的长期依赖关系。它是传统RNN的扩展,与长短期记忆(LSTM)网络具有相似性。我们将简要了解GRU模型以及如何帮助客户在PyThon中使用GRU实现序列数据......
  • 【Python绘画】画笑脸简笔画
    本文收录于《一起学Python趣味编程》专栏,从零基础开始,分享一些Python编程知识,欢迎关注,谢谢!文章目录一、前言二、代码示例三、知识点梳理四、总结一、前言本文介绍如何使用Python的海龟画图工具turtle,画笑脸简笔画。什么是Python?Python是由荷兰人吉多·范罗苏......
  • 代码实操学会socket网络编程
    一、网络编程接口网络编程接口是一组提供给开发者使用的函数和方法集合,用于在应用程序中实现网络通信功能。它提供了一种抽象层,使得开发者能够使用高级编程语言(如C、C++、Java、Python等)来进行网络编程,而无需直接处理底层的网络协议和细节。网络编程接口的功能和作用包括:......