Python- socket编程

news2025/6/25 1:58:55

Python中的socket模块为网络通信提供了基础API,使我们能够在应用程序中实现低级的网络交互。使用socket编程,可以创建TCP、UDP和RAW sockets来进行数据通信。

以下是Python socket 编程的简要概述:

1. 核心概念

  • Socket: 通信的端点,通常用于建立多个系统之间的连接。
  • Bind: 将套接字与特定的IP地址和端口号关联。
  • Listen: 在套接字上监听传入的连接。
  • Accept: 接受传入的连接请求。
  • Connect: 初始化与服务器的连接。

2. 基本流程

服务器端:
  1. 创建套接字: socket.socket()
  2. 绑定套接字到地址: bind((host, port))
  3. 监听连接: listen()
  4. 接受连接: accept()
  5. 读取/发送数据: recv()/send()
  6. 关闭套接字: close()
客户端:
  1. 创建套接字: socket.socket()
  2. 连接到服务器: connect((host, port))
  3. 读取/发送数据: recv()/send()
  4. 关闭套接字: close()

3. 主要函数/方法

  • socket(): 创建新的socket对象。
  • bind(): 绑定地址到套接字。
  • listen(): 开始监听传入的连接。
  • accept(): 接受客户端连接,并返回(connection, address)。
  • connect(): 连接到远程地址。
  • recv(): 从套接字接收数据。
  • send(): 将数据发送到套接字。
  • close(): 关闭套接字。

4. TCP

一个简单的TCP服务器和客户端的示例。

TCP服务器
import socket
import json

def start_server():
    # 创建socket对象
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 获取主机名称
    # host = socket.gethostname()
    host = "127.0.0.1"
    port = 12345

    # 绑定到端口
    server_socket.bind((host, port))

    # 设置最大连接数,超过后排队
    server_socket.listen(5)

    print("Server is listening...")
    while True:
        # 建立客户端连接
        client_socket, addr = server_socket.accept()
        print(f"Connection from {addr}")

        data = client_socket.recv(1024).decode('utf-8')
        json_data = json.loads(data)
        print(f"Received {json_data} from {addr}")

        client_socket.send(data.encode('utf-8'))
        client_socket.close()

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

def start_client():
    # 创建socket对象
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 获取本地主机名
    # host = socket.gethostname()
    host = "127.0.0.1"
    port = 12345

    print(host)
    # 连接到服务器
    client_socket.connect((host, port))

    message = {
        "name": "Alice",
        "age": 30
    }

    json_message = json.dumps(message)
    # 发送数据
    client_socket.send(json_message.encode('utf-8'))

    # 接收数据,最多接收1024字节
    data = client_socket.recv(1024).decode('utf-8')
    json_data = json.loads(data)
    print(f"Received from server: {json_data}")

    client_socket.close()

if __name__ == '__main__':
    start_client()

运行结果如下:

运行效果

5. UDP

与TCP不同,UDP是一个无连接的协议。使用UDP,不需要建立和断开连接。每个数据报都是一个独立的消息。

UDP 服务器
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('127.0.0.1', 12345))
while True:
    data, addr = s.recvfrom(1024)
    print(f"Received {data.decode('utf-8')} from {addr}")
    s.sendto(data, addr)
UDP 客户端
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
    message = input("Enter message: ").encode('utf-8')
    s.sendto(message, ('127.0.0.1', 12345))
    data, addr = s.recvfrom(1024)
    print(f"Received {data.decode('utf-8')} from {addr}")

运行结果如下:

运行效果

6. ICMP

RAW sockets是一种低级的通信机制,允许我们直接发送和接收底层网络协议的数据包,如ICMP、IP等。在Python中使用RAW sockets通常需要root权限或适当的权限,因为它涉及到操作系统级的网络操作。

以下是使用RAW socket在Python中发送一个ICMP Echo Request(通常称为ping请求)的示例。注意,此代码是在Linux上工作的,因为Windows上的raw socket行为与Linux不同。

import socket
import struct
import time

def checksum(data):
    s = 0
    n = len(data) % 2
    for i in range(0, len(data)-n, 2):
        s += (data[i] + (data[i+1] << 8))
    if n:
        s += data[i+1]
    while (s >> 16):
        s = (s & 0xFFFF) + (s >> 16)
    s = ~s & 0xFFFF
    return s

def create_icmp_echo_request():
    icmp_type = 8
    icmp_code = 0
    icmp_checksum = 0
    icmp_identifier = 1
    icmp_sequence_number = 1

    # ICMP header
    header = struct.pack("!BBHHH", icmp_type, icmp_code, icmp_checksum, icmp_identifier, icmp_sequence_number)
    
    data = struct.pack("!d", time.time())

    icmp_checksum = checksum(header + data)
    header = struct.pack("!BBHHH", icmp_type, icmp_code, icmp_checksum, icmp_identifier, icmp_sequence_number)
    
    return header + data

def main():
    target_host = "172.20.7.84" 
    icmp_proto = socket.getprotobyname('icmp')
    
    # Create a raw socket
    s = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp_proto)
    s.sendto(create_icmp_echo_request(), (target_host, 0))

    # Wait for a reply
    while True:
        data, addr = s.recvfrom(1024)
        if addr[0] == target_host:
            print(data)
            print(f"Received reply from {addr[0]}")
            break

if __name__ == "__main__":
    main()

这只是一个简单的示例,它发送一个ICMP请求并等待一个响应。在生产环境中使用RAW sockets时,需要处理更多的边缘情况和错误,以及考虑多种协议和包格式。

7. 错误处理

在socket编程中,特别是在网络中,总是可能发生各种错误。为了编写健壮的应用程序,应该捕获socket.error异常并据此采取适当的行动。

8. 高级

除了基础的socket编程,Python还提供了更高级的工具和模块,例如selectorsasyncio,用于处理多并发连接或异步IO。

总之,socket编程是计算机网络和分布式系统中的一个基本概念。Python提供了一个强大而简单的API来处理套接字,使得网络编程变得相对容易。


以下是关于ICMP示例程序的几点说明:

(1)当在Python中使用struct.pack方法,表示正在执行结构化的打包操作,将多个数据项打包成一个字节串。它通常用于处理二进制数据和底层的数据结构,例如网络协议。

在ICMP示例代码段中:

header = struct.pack("!BBHHH", icmp_type, icmp_code, icmp_checksum, icmp_identifier, icmp_sequence_number)

我们逐一解析这行代码:

  1. !: 这是字节顺序标记。感叹号!表示网络字节顺序,也就是大端字节序。在网络通讯中,大端字节序是常用的标准。

  2. BBHHH: 这是格式字符串,它告诉struct.pack如何打包接下来的数据。

    • B: 无符号字符(1个字节)
    • H: 无符号短整数(2个字节)

    因此,BBHHH表示打包了2个1字节的无符号字符和3个2字节的无符号短整数,总共8个字节。

  3. 后面的参数列表(icmp_type, icmp_code, icmp_checksum, icmp_identifier, icmp_sequence_number)是要打包的实际数据。这些数据的顺序和大小应该与格式字符串BBHHH匹配。

具体到ICMP头部的内容:

  • icmp_type: ICMP消息的类型(1字节)
  • icmp_code: 与ICMP类型相关的特定代码(1字节)
  • icmp_checksum: 对整个ICMP数据包计算得到的校验和(2字节)
  • icmp_identifier: 用于唯一标识此请求的标识符,通常是发送进程的PID(2字节)
  • icmp_sequence_number: 该请求的序列号,通常是从0开始递增的(2字节)

通过struct.pack,这些数据被格式化和打包成一个连续的8字节的字节串,然后可以直接发送到网络上。

(2)在下面的代码片段中,使用struct.pack来将一个双精度浮点数(即Python中的float)打包为一个二进制格式的字符串。这样的操作常用于将高级的数据类型转换为可以在网络上发送或在二进制文件中存储的格式。

data = struct.pack("!d", time.time())

让我们逐步解析这段代码:

  1. struct.pack: 这是Python中的struct模块提供的函数,用于将给定的数据格式化(或打包)为一个二进制字符串。

  2. "!d": 这是一个格式字符串,它告诉struct.pack函数如何格式化后续的数据。

    • !: 指定字节顺序为网络字节顺序(也就是大端字节序)。

    • d: 表示一个双精度浮点数。这通常占用8个字节。

  3. time.time(): 这是Python中time模块的一个函数,返回当前时间的时间戳,类型为float。这表示从某个固定的起点(通常是1970年1月1日0点,称为Unix纪元)到现在的秒数。

这段代码的目的是将当前的时间戳转换为一个8字节的二进制字符串。这在网络编程中很有用,尤其是当我们想在数据包中包含一个时间戳,以便在接收端可以解码并使用它。例如,在ICMP的ping工具中,发送时间戳可以帮助计算往返时间(RTT)。

(3)下面这段代码使用socket模块的getprotobyname方法来查询指定协议名的协议号。具体来说,它查询“icmp”协议的协议号。

icmp_proto = socket.getprotobyname('icmp') 

让我们详细了解这段代码:

  1. socket: 这是Python的标准库之一,它提供了套接字编程的工具和函数。

  2. getprotobyname: 这个函数的作用是返回与给定的协议名称关联的协议号。

  3. 'icmp': 这是传递给getprotobyname函数的参数,代表互联网控制消息协议(ICMP)。

当这个函数被调用时,它会查找系统的协议配置文件(通常是/etc/protocols)来找到与“icmp”匹配的协议号。通常,ICMP的协议号为1,所以函数通常会返回1

为什么这个是重要的?当创建原始套接字(raw socket)用于发送或接收ICMP消息时,我们需要告诉系统正在使用哪种协议。icmp_proto这个变量保存的值(即ICMP的协议号)就是这个目的。当创建一个原始套接字并指定ICMP协议时,系统就知道我们要处理ICMP数据包。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1086025.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PTrade获取当日n个季度前的日期所处季度的最后一天——时间相关函数4

本文介绍的函数用于获取当日n个季度前的日期所处季度的最后一天&#xff08;有点绕&#xff0c;看后面例子就好理解了&#xff09;。 源码 def last_day_of_quarter_before_n_quarters(n):"""获取当日n个季度前的日期所处季度的最后一天:return: 当日n个季度前…

leetcode 打家劫舍篇

198. 打家劫舍 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一个代表每个…

【嵌入式】STM32F031K4U6、STM32F031K6U6、STM32F031K6T6主流ARM Cortex-M0基本型系列MCU规格参数

一、电路原理图 【嵌入式】STM32F031K4U6、STM32F031K6U6、STM32F031K6T6主流ARM Cortex-M0基本型系列MCU —— 明佳达 二、规格参数 1、STM32F031K4U6&#xff08;16KB&#xff09;闪存 32UFQFPN 核心处理器&#xff1a;ARM Cortex-M0 内核规格&#xff1a;32 位单核 速度&a…

喜报!冲量在线中标中国电信北京公司2023年基于通用GPU的可信执行环境技术的研究项目

近日&#xff0c;冲量在线中标中国电信北京公司2023年基于通用GPU的可信执行环境的研究项目&#xff01;基于通用GPU的可信执行环境技术&#xff0c;完成业界领先的基于国产可信芯片的AI算力平台建设。 通过平台TEEGPU的隐私计算能力&#xff0c;给现有的AI智算平台在可信计算方…

必知必会的22种设计模式(GO语言)

日常工作中免不了使用设计模式&#xff0c;那么你使用了哪些设计模式呢&#xff1f; 设计模式是什么&#xff1f; 设计模式是一种在软件设计中对常见问题的通用解决方案。 它们是经过验证的、可重用的设计思想&#xff0c;可以帮助解决开发过程中遇到的各种问题。 设计模式…

碰撞检测算法——分离轴算法在Unity中实现(二)

一、介绍 分离轴算法&#xff08;简称SAT&#xff09;通常用于检查两个简单多边形&#xff08;凸边形&#xff09;之间或多边形与圆之间的碰撞。本质上&#xff0c;如果您能够绘制一条线来分隔两个多边形&#xff0c;则它们不会发生碰撞&#xff0c;如果找不到一条线来分割两个…

卷积神经网络CNN基础知识

目录 1 前言2 卷积神经网络CNN2.1 LeNet-5相关介绍2.2 CNN基本结构2.2.1 卷积层2.2.2 池化层&#xff08;下采样层&#xff09;2.2.3 全连接层2.2.3.1激励层&#xff08;非线性激活&#xff09;2.2.3.2 线性层2.2.3.3 Dropout层2.2.3.4 总结 2.3 图像的上采样和下采样2.3.1 上采…

vue2 .sync 修饰符

vue2 .sync 修饰符 **创建 工程&#xff1a; H:\java_work\java_springboot\vue_study ctrl按住不放 右键 悬着 powershell H:\java_work\java_springboot\js_study\Vue2_3入门到实战-配套资料\01-随堂代码素材\day04\准备代码\13-sync修饰符 vue --version vue create v-sy…

高效团队协作软件推荐:提升工作效率的优选方案!

使用团队协作软件有什么好处&#xff1f;可以摆脱过时的电子表格&#xff0c;有了单一的真实来源&#xff0c;您可以随时检查任何任务并获得可用的最新信息。 一目了然地查看所有正在进行的工作&#xff0c;看板式面板、甘特图和燃尽图等可视化工具可让您随时轻松获得项目的高级…

基本微信小程序的购物商城系统

项目介绍 随着互联网的趋势的到来&#xff0c;各行各业都在考虑利用互联网将自己的信息推广出去&#xff0c;最好方式就是建立自己的平台信息&#xff0c;并对其进行管理&#xff0c;随着现在智能手机的普及&#xff0c;人们对于智能手机里面的应用购物平台小程序也在不断的使…

javaweb:mybatis:mapper(sql映射+代理开发+配置文件之设置别名、多环境配置、顺序+注解开发)

1.0版本 sql映射文件实现 流程 首先程序进入启动类MyBatisDemo.java中&#xff0c;读取配置文件mybatis-config.xml 再由mybatis-config的mappers属性 <mappers><mapper resource"UserMapper.xml"></mapper></mappers>找到sql映射文件Use…

大数据精准营销一站式解决你的获客难题

自从千禧年之后&#xff0c;互联网逐渐走进每家每户&#xff0c;改变了人们的生活习惯&#xff0c;也改变了运营人的营销模式&#xff0c;使我们从传统营销转向互联网营销&#xff01; 新时代的到来&#xff0c;智能手机的问世又使互联网营销达到了一个新的高潮&#xff01;一些…

WEB 跨域

![Alt](https://img-home.csdnimg.cn/images/20220524100510.png 60x60 问题描述&#xff1a; web端的跨域&#xff1a; 响应头中出现重复&#xff0c;等其他关于跨域的奇奇怪怪的问题以下排查方式够了。 注&#xff1a; 以下最终解决问题的方式是将处理跨域的地方集中在一个…

JS之同步异步promise、async、await

promise异步操作 Promise是异步编程的一种解决方案 JavaScript异步与同步解析 学习promise前我们先来了解下什么是异步&#xff1f; 基本概念&#xff1a; 消息队列中的任务分为宏任务与微任务;调用栈也可以称为主线程 首先我们要知道js是单线程语言&#xff0c;也就是说…

基于NLopt的C语言非线性优化案例

以官方给的例程&#xff0c;重新梳理&#xff0c;以供理解NLopt的使用。 问题被定义为&#xff1a; min ⁡ x ∈ R 2 x 2 s u b j e c t t o x 2 ≥ 0 , x 2 ≥ ( a 1 x 1 b 1 ) 3 , a n d x 2 ≥ ( a 2 x 1 b 2 ) 3 f o r p a r a m e t e r s a 1 2 , b 1 0 , a 2 − 1…

Edge使用猴油脚本实战(实验室安全考试系统刷在线时长——网站永久自动刷新)

介绍 篡改猴 (Tampermonkey) 是拥有 超过 1000 万用户 的最流行的浏览器扩展之一。它允许用户自定义并增强您最喜爱的网页的功能。用户脚本是小型 JavaScript 程序&#xff0c;可用于向网页添加新功能或修改现有功能。使用 篡改猴&#xff0c;您可以轻松在任何网站上创建、管理…

标题:协同云办公:打破传统模式,提升工作效率!

随着科技的迅速发展&#xff0c;传统办公模式已经难以满足现代企业的需求。为了提高工作效率和协作能力&#xff0c;越来越多的企业开始采用协同云办公。协同云办公通过云计算、大数据等技术&#xff0c;打破了传统办公模式的束缚&#xff0c;为企业带来了前所未有的便捷与高效…

geecg-uniapp 源码下载运行 修改端口号 修改tabBar 修改展示数据(1)

APP体验&#xff1a; http://jeecg.com/appIndex技术官网&#xff1a; http://www.jeecg.com安装文档&#xff1a; 快速开始 JeecgBoot 开发文档 看云视频教程&#xff1a; 零基础入门视频官方支持&#xff1a; http://jeecg.com/doc/help 一&#xff0c;下载安装 源码下载…

react中ant.design框架配置动态路由

目录 什么是动态路由&#xff1f; 应用场景&#xff1a; ant.design动态路由如何配置&#xff1a; 首先&#xff1a;找到app.tsx文件 然后&#xff1a;找到menuHeaderRender 其次&#xff1a;修改menuHeaderRender为menuDataRender​编辑 最后&#xff1a;在箭头函数里re…

PyTorch 深度学习之加载数据集Dataset and DataLoader(七)

1. Revision: Manual data feed 全部Batch&#xff1a;计算速度&#xff0c;性能有问题 1 个 &#xff1a;跨越鞍点 mini-Batch:均衡速度与性能 2. Terminology: Epoch, Batch-Size, Iteration DataLoader: batch_size2, sheffleTrue 3. How to define your Dataset 两种处…