Python- socket编程

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 jsondef 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 jsondef start_client():# 创建socket对象client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 获取本地主机名# host = socket.gethostname()host = "127.0.0.1"port = 12345print(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 sockets = 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 sockets = 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 timedef checksum(data):s = 0n = len(data) % 2for 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 & 0xFFFFreturn sdef create_icmp_echo_request():icmp_type = 8icmp_code = 0icmp_checksum = 0icmp_identifier = 1icmp_sequence_number = 1# ICMP headerheader = 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 + datadef main():target_host = "172.20.7.84" icmp_proto = socket.getprotobyname('icmp')# Create a raw sockets = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp_proto)s.sendto(create_icmp_echo_request(), (target_host, 0))# Wait for a replywhile True:data, addr = s.recvfrom(1024)if addr[0] == target_host:print(data)print(f"Received reply from {addr[0]}")breakif __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.rhkb.cn/news/156357.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机毕业设计 it职业生涯规划系统的设计与实现 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

Centos (含Rocky-Linux) VSFTPD 简单设置

本文并非深入讨论vsftp配置的文章&#xff0c;仅以能连通为目的&#xff0c;适合那些临时需要上传点东西到服务器的场景。 一、安装 dnf -y updatednf -y install vsftpdsystemctl start vsftpdsystemctl enable vsftpd二、防火墙 开放21端口&#xff1a; firewall-cmd --zo…

按键中断小灯蜂鸣器风扇

按键1实现小灯亮灭&#xff0c;按键2实现蜂鸣器&#xff0c;安静3实现风扇 src/key_it.c #include"key_it.h"void key3_it_config() {//RCC使能GPIOF时钟RCC->MP_AHB4ENSETR | (0x1<<5);GPIOF->MODER & (~(0x3<<16));EXTI->EXTICR3 &…

RustDay03——记录刷完Rust100题

刷了两三天Rust&#xff0c;终于把Rust100题刷完了&#xff0c;小小记录一下 明天白天的时候重开账户开题写答案

ThreeJS-3D教学七-交互

在threejs中想要选中一个物体&#xff0c;点击或者鼠标悬浮&#xff0c;又或者移动端的touch事件&#xff0c;核心都是通过new THREE.Raycaster完成的。这里用到了一个概念&#xff0c;即我们点击时的 屏幕坐标 转换为 three中的3D坐标。 先看效果图&#xff1a; 代码是&#…

2023全国大学生软件测试大赛开发者测试练习题99分答案(ScapegoatTree2023)

2023全国大学生软件测试大赛开发者测试练习题99分答案(ScapegoatTree2023) 题目详情题解代码(直接全部复制到test类中即可)提示:该题只需要分支覆盖得分即可,不需要变异得分 题目详情 题解代码(直接全部复制到test类中即可) package net.mooctest;import static org.…

Zabbix安装出现必要条件检查失败

问题描述 今天在某朋友部署新环境的Zabbix时&#xff0c;系统出现如下的检查失败情况。此环境的基础部分不是我负责&#xff0c;而是其它项目共存的PHP环境&#xff0c;也是挺奇怪的。一般来说&#xff0c;不应该将zabbix与其它系统部署在一起&#xff0c;没有条件哪怕时Docke…

在服务器上解压.7z文件

1. 更新apt sudo apt-get update2. 安装p7zip sudo apt-get install p7zip-full3. 解压.7z文件 7za x WN18RR.7z

OpenCV4(C++)—— 直方图

文章目录 前言一、计算直方图二、归一化三、直方图均衡化四、直方图匹配 前言 直方图(Histogram)最开始在统计学中被提出&#xff0c;由一系列高度不等的纵向条纹或线段表示数据分布的情况。 一般用横轴表示数据类型&#xff0c;纵轴表示分布情况。在图像领域&#xff0c;直方…

旅游网站HTML

代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>旅游网</title> </head> <body><!--采用table编辑--> <!--最晚曾table,用于整个页面那布局--><table width&q…

Java I/O 的 OutputStream 输出流相关知识点详解

Java 17 的 I/O 基础 OutputStream 篇 对于 OutputStream 主要是字节流类型的输出流。 OutputStream OutputStream 抽象类是所有字节输出流类的超类。输出流接受输出字节并将它们发送到某个接收器中。 同样该抽象类需要一个子类来继承实现始终提供至少一种写入一个字节输出的…

es6(二)——常用es6说明

ES6的系列文章目录 es6&#xff08;一&#xff09;——var和let和const的区别 文章目录 ES6的系列文章目录一、变量的结构赋值1.数组的结构赋值2.对象的结构赋值 二、模板字符串三、扩展运算符1.字符串的使用2.数组的使用 四、箭头函数1.普通函数的定义2.箭头函数的定义3.箭头…

简单大方的自我介绍 PPT 格式

自我介绍是展示自己的机会&#xff0c;同时也是展现自信和魅力的重要时刻。通过简单大方的PPT格式&#xff0c;可以更好地展示自己的个性和才华。下面是一些建议&#xff0c;帮助你在自我介绍中展现自信和魅力。 1. 打造简洁而有吸引力的PPT布局&#xff1a; - 选择简洁大方的背…

数据库常见面试题--MySQL

梳理面试过程中数据库相关的常见问题&#xff0c;需要说明的是&#xff0c;这篇文章主要是基于MySQL数据库&#xff0c;其他类型的数据库还请自行参考使用。 数据库概述 为什么使用数据库 1、数据库增删改查更方便 2、提供了事务的能力 本质是更好的管理数据。 数据库体系结…

(部署服务器系列一)虚拟机模拟部署服务器

1、下载安装vmware 15 &#xff08;win7最高支持版&#xff09; 2、下载安装CentOS 配置2核2g&#xff08;最少&#xff09;磁盘100g&#xff08;不会实际占有&#xff09;选择时区-上海配置分区&#xff1a;https://blog.csdn.net/qq_35363507/article/details/127390889 &a…

借助PLC-Recorder,汇川中型PLC(AM、AC系列,CODESYS平台)2ms高速采集的方法

高速数据采集要保证速度&#xff0c;也要保证时刻的准确性。在windows系统里&#xff0c;时间稳定性是个很难的问题。如果PLC发送的数据里带有时间信息&#xff0c;则可以由PLC来保证采样周期的稳定性。 从V2.12版本开始&#xff0c;PLC-Recorder软件可以处理发送电文里的时间…

Ubuntu输入正确密码重新跳到登录界面

Ubuntu输入正确密码重新跳到登录界面 问题描述 输入正确的密码登录后闪一下又回到锁屏界面 输入正确的密码后还是回到这个界面 产生的原因 /etc/profile或者/etc/enviroment出现了问题,导致无法正常登录 该错误产生的原因不止一个 这里是因为/etc/profile或者/etc/enviromen出…

收银系统商品定价设计思考

一、背景 因为门店系统里商品总共也就几万款&#xff0c;一直以来都是根据条码由总部统一定价销售&#xff0c;现在有加盟店&#xff0c;各门店也有进行各自促销活动的需求&#xff0c;这就需要放开门店自主定价权&#xff0c;所以近段时间系统在商品定价上做了扩展。 二、商…

如何在雷电模拟器上安装Magisk并加载movecert模块抓https包(一)

环境&#xff1a;win10 64位&#xff0c;雷电模拟器版本4.0.78&#xff0c;Android版本7.1.2。 前几天写了一篇文章如何在逍遥模拟器上加载Magisk模块-CSDN博客&#xff0c;因为最近很忙&#xff0c;所以直到今天才有空写这一篇&#xff0c;记录如何在雷电模拟器上安装Magisk并…

基于uniapp的商城外卖小程序

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…