【python高级】342-TCP服务器开发流程

CS模式:客户端-服务端模式

TCP客户端开发流程介绍(五步)(C端)
1.创建客户端套接字对象
2.和服务端套接字建立连接
3.发送数据
4.接收数据
5.关闭客户端套接字
TCP服务端开发流程(七步)(S端)
1.创建服务端端套接字对象
2.绑定端口号
3.设置监听
4.等待接受客户端的连接请求
5.接收数据
6.发送数据
7.关闭套接字

TCP客户端程序开发

import socket# 第一步:创建客户端套接字对象
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # socket.AF_INET表示IPV4,socket.SOCK_STREAM表示TCP协议# 第二步:创建连接
tcp_client_socket.connect(("127.0.0.1", 8000))  # 参数是个元组# 第三步:发送数据到服务器端
tcp_client_socket.send("hello".encode("utf-8"))  # 这里将字符串编码成二进制数据# 第四步:接收服务器端返回的数据
recv_data = tcp_client_socket.recv(1024).decode("utf-8")  # 1024表示本次接收的最大字节数,decode解码
print(f"接收到的数据为:{recv_data}")  # 将二进制数据解码成字符串# 第五步:关闭套接字对象
tcp_client_socket.close()

tip:发送和接受的都要是二进制数据,所以要用encode和decode方法将字符串转换成二进制数据

  • encode():将字符串转换成二进制数据
  • decode():将二进制数据转换成字符串

关于socket.AF_INET、socket.SOCK_STREAM常量的介绍:

  • socket.AF_INET(IPv4)
    • 这是 Python 中socket模块里的一个常量,AF_INET代表 Address Family(地址族)为INET,用于指定网络通信使用的地址族是 IPv4 地址族。
    • 当创建一个套接字(socket)时,通过指定AF_INET,告诉操作系统这个套接字将用于基于 IPv4 协议的网络通信。
  • socket.SOCK_STREAM(TCP)
    • 这是socket模块中的另一个常量,用于指定套接字的类型为流套接字。
      • 当和AF_INET一起使用创建套接字时(如前面代码示例中的socket.socket(socket.AF_INET, socket.SOCK_STREAM)),它表示创建的是一个基于 TCP(Transmission Control Protocol)协议的流套接字。TCP 是一种面向连接的、可靠的传输协议,SOCK_STREAM类型的套接字利用 TCP 协议提供的特性,如三次握手建立连接、数据的可靠传输(通过确认、重传等机制)、流量控制和拥塞控制等。
      • 这种类型的套接字适用于需要保证数据准确无误地传输的应用场景,比如 HTTP(超文本传输协议)用于网页浏览,SMTP(简单邮件传输协议)用于发送电子邮件等。它提供了一个字节流的接口,应用程序可以像读写文件一样通过这个套接字进行数据的发送和接收,而不必担心数据的丢失或损坏,因为 TCP 协议在底层会处理这些问题。

TCP服务端程序开发(重点)

开发的七步:
1.创建服务端套接字对象
2.绑定端口号
3.设置监听
4.等待接受客户端的连接请求:类似于input() → accept()阻塞
5.接收数据
6.发送数据
7.关闭套接字

服务器如何判断是哪个客户端连接:
通过accept()方法返回的套接字对象来区分不同的客户端

import socket# 1.创建服务端套接字对象
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # socket.AF_INET表示IPV4,socket.SOCK_STREAM表示TCP协议# 2.绑定端口号
tcp_server_socket.bind(("127.0.0.1", 8000))  # 如果是本机,可以不写ip地址# 3.设置监听
tcp_server_socket.listen(128)  # 128表示最大连接数# 4.等待接受客户端的连接请求
new_socket, ip_port = tcp_server_socket.accept()  # 阻塞状态,等待客户端连接
# tcp_server_socket对象主要用于接收客户端连接:绑定端口、设置监听、接收连接
# new_socket对象主要用于接收和发送数据
print(f"新连接的客户端地址为:{ip_port}")
print(f"新连接的客户端socket对象为:{new_socket}")# ================================================
# 5.接收数据
recv_data = new_socket.recv(1024).decode("utf-8")  # 1024表示本次接收的最大字节数,decode解码	
print(f"接收到的数据为:{recv_data}")# 6.发送数据
new_socket.send("信息已收到".encode("utf-8"))  # 将字符串编码成二进制数据# 7.关闭新套接字对象(关闭后不能收发消息)和服务端套接字对象(不能接收新连接)
new_socket.close()
tcp_server_socket.close()

当客户端发送信息后,接收到的data是一个元组,下面是个栗子,元组有两个元素,第一个元素是套接字对象,第二个元素是客户端的地址(也是元组)

(<socket.socket fd=432, family=AddressFamily.AF_INET, ttype=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8000), raddr=('127.0.0.1', 60925)>, ('127.0.0.1', 60925)
)

注意事项:

  • 明确自己开发的到底是客户端还是服务端
    • 客户端:connect()、send()、recv()、close()
    • 服务端:socket()、bind()、listen()、accept()、recv()、send()、close()
  • 两个对象要分清楚
    • tcp_server_socket:主要用于接收客户端连接
      • 内部只有服务器本身的信息,可以绑定端口、设置监听、接收连接
    • new_socket:主要用于接收和发送数据
      • 内部既有客户端又有服务器端信息,可以接收和发送数据
      • 只能通过这个新套接字来收发数据

服务器端面向对象版本

都是七步,不变

面向对象,先分析有哪些对象,创建类,属性和方法


# 第一步:创建类
class WebServer:# 第四步:创建初始化方法,初始化套接字对象def __init__(self):# 1.创建套接字对象self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # AF_INET表示IPV4,SOCK_STREAM表示TCP协议# 2.绑定ip和端口号self.tcp_server_socket.bind(("127.0.0.1", 8000))  # 如果是本机,可以不写ip地址# 这里的8000端口不会随着服务器关闭而释放,需要设置端口复用,端口复用在下一篇笔记# 3.设置监听self.tcp_server_socket.listen(128)  # 128表示最大连接数# 第五步:定义一个start方法,启动服务器,接收客户端连接def start(self):while True:# 4.等待接受客户端的连接请求new_socket, ip_port = self.tcp_server_socket.accept()# 5.接收数据recv_data = new_socket.recv(1024).decode("utf-8")print(f"接收到的数据为:{recv_data}")# 6.发送数据new_socket.send("信息已收到".encode("utf-8"))# 7.关闭套接字(只能接收一次信息)# 不能关闭tcp_server_socket,否则无法继续接收新连接new_socket.close()# 目前一次只能接收一个客户端,因为是单进程# 如果希望服务器可以同时和多个客户端收发消息,需要多进程(多任务编程)# 第二步:实例化对象
ws = WebServer()# 第三步:调用start方法,启动服务器,接收客户端连接
ws.start()

端口复用

在上一次关闭服务器后,端口不会立即释放,需要设置端口复用,才能继续使用此端口

import socketclass WebServer:# 3、定义一个__init__方法,初始化套接字对象def __init__(self):self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 设置端口复用(在上一次关闭服务器后,端口不会立即释放,需要设置端口复用)self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)  # 参数2:SOL_SOCKET表示当前套接字对象,参数3:SO_REUSEADDR表示复用的地址,参数4:True表示开启端口复用(默认是false,要等待很长时间端口才会自动释放)self.tcp_server_socket.bind(("127.0.0.1", 8000))  # 如果是本机,可以不写ip地址self.tcp_server_socket.listen(128)  # 128表示最大连接数# 4、定义一个start方法,启动服务器,接收客户端连接def start(self):while True:# 等待接受客户端的连接请求new_socket, ip_port = self.tcp_server_socket.accept()# 调用自身的handle_request()方法,用于接收和发送消息(封装性)self.handle_request(new_socket, ip_port)# 5、定义一个handle_request方法,用于接收和发送消息def handle_request(self, new_socket, ip_port):# 接收某个客户端发送过来的消息recv_data = new_socket.recv(1024).decode("utf-8")  # 实际工作中一条数据大小在1~1.5k之间print(f"接收到的数据为:{recv_data}")# 发送消息给客户端new_socket.send("信息已收到".encode("utf-8"))# 关闭套接字new_socket.close()# 定义一个程序的执行入口
if __name__ == "__main__":# 1、实例化服务器对象server = WebServer()# 2、启动服务器server.start()

开发注意事项

1.当TCP客户端程序想要和TCP服务端程序进行通信的时候必须要先建立连接
2.TCP客户端程序一般不需要绑定端口号,因为客户端是主动发起建立连接的。
3.TCP服务端程序必须绑定端口号,否则客户端找不到这个TCP服务端程序。
4.listen后的套接字是被动套接字,只负责接收新的客户端的连接请求,不能收发消息。
5.当TCP客户端程序和TCP服务端程序连接成功后,TCP服务器端程序会产生一个新的套接字,收发客户端消息使用该套接字。
6.关闭accept返回的套接字意味着和这个客户端已经通信完毕。
7.当客户端的套接字调用close后,服务器端的recv会解阻塞,返回的数据长度为O,服务端可以通过返回数据的长度来判断客户端是否
已经下线,反之服务端关闭套接字,客户端的recv也会解阻塞,返回的数据长度也为0。

UDP客户端

# 导入socket模块
import socket# 创建UDP套接字对象
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 连接服务器,发送数据
udp_socket.sendto("消息".encode("utf-8"), ("127.0.0.1", 8000))# 关闭套接字
udp_socket.close()

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

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

相关文章

软件测试之测试用例

文章目录 测试用例测试用例的编写总结 测试用例 测试用例:描述测试点执行的文档(测试输入、执行条件、预期结果等) 作用 1.测试点能被精准执行 2.便于团队合作测试用例核心内容 用例编号、用例标题、所属模块、优先级、前置条件、测试步骤、测试数据、预期结果 测试用例的编写…

微机接口课设——基于Proteus和8086的打地鼠设计(8255、8253、8259)

原理图设计 汇编代码 ; I/O 端口地址定义 IOY0 EQU 0600H IOY1 EQU 0640H IOY2 EQU 0680HMY8255_A EQU IOY000H*2 ; 8255 A 口端口地址 MY8255_B EQU IOY001H*2 ; 8255 B 口端口地址 MY8255_C EQU IOY002H*2 ; 8255 C 口端口地址 MY8255_MODE EQU IOY003H*2 ; …

I.MX6U 启动方式详解

一、启动方式选择 BOOT 的处理过程是发生在 I.MX6U 芯片上电以后,芯片会根据 BOOT_MODE[1:0]的设置 来选择 BOOT 方式。 BOOT_MODE[1:0]的值是可以改变的,有两种方式,一种是改写 eFUSE(熔 丝),一种是修改相应的 GPIO 高低电平。第一种修改 eFUSE 的方式只能修改一次,后面就…

下载运行Vue开源项目vue-pure-admin

git地址&#xff1a;GitHub - pure-admin/vue-pure-admin: 全面ESMVue3ViteElement-PlusTypeScript编写的一款后台管理系统&#xff08;兼容移动端&#xff09; 安装pnpm npm install -g pnpm # 国内 淘宝 镜像源 pnpm config set registry https://registry.npmmirror.com/…

springboot-starter版本升级es版本问题

一、背景说明 版本漏洞处理&#xff0c;springboot版本升级&#xff0c;es版本暂不升级&#xff0c;但是pom引用中es版本一直为7.17.15高版本&#xff0c;不想显示声明版本&#xff0c;定位具体问题&#xff0c;最后还是重新定义了版本进行处理。 二、异常情况 这里看4.4.18是…

模型优化之知识蒸馏

文章目录 知识蒸馏优点工作原理示例代码 知识蒸馏优点 把老师模型中的规律迁移到学生模型中&#xff0c;相比从头训练&#xff0c;加快了训练速度。另一方面&#xff0c;如果学生模型的训练精度和老师模型差不多&#xff0c;相当于得到了规模更小的学生模型&#xff0c;起到模…

Hadoop集群(HDFS集群、YARN集群、MapReduce​计算框架)

一、 简介 Hadoop主要在分布式环境下集群机器&#xff0c;获取海量数据的处理能力&#xff0c;实现分布式集群下的大数据存储和计算。 其中三大核心组件: HDFS存储分布式文件存储、YARN分布式资源管理、MapReduce分布式计算。 二、工作原理 2.1 HDFS集群 Web访问地址&…

使用 acme.sh 申请域名 SSL/TLS 证书完整指南

使用 acme.sh 申请域名 SSL/TLS 证书完整指南 简介为什么选择 acme.sh 和 ZeroSSL&#xff1f;前置要求安装过程 步骤一&#xff1a;安装 acme.sh步骤二&#xff1a;配置 ZeroSSL 证书申请 方法一&#xff1a;手动 DNS 验证&#xff08;推荐新手使用&#xff09;方法二&#xf…

# 起步专用 - 哔哩哔哩全模块超还原设计!(内含接口文档、数据库设计)

↑ 上方下载文档 (大小374KB) 接口文档预览 (超过50个接口) 一、数据库25张表er-关系清晰构图&#xff01;(tip: 鼠标右键图片 > 放大图像) 二、难点/经验 详细说明 热门评论排序评论点赞列表|DTO封装经验分享|精华接口文档说明 组员都说喜欢分档对应枚举码 如果这篇文章…

掌握 Ansys ACP 中的参考方向:简化复杂的复合材料设计

概括 在复合材料分析领域&#xff0c;精度至关重要&#xff0c;尤其是在定义纤维方向和铺层时。Ansys ACP&#xff08;Ansys Composite PrepPost&#xff09;提供了强大的工具来建立参考方向&#xff0c;这是实现精确结构模拟的关键步骤。在本博客中&#xff0c;我们将揭开在 …

牵手红娘:牵手App红娘助力“牵手”,脱单精准更便捷

随着互联网的普及&#xff0c;现代青年的社交圈层加速扩大&#xff0c;他们的恋爱观也正经历着前所未有的转变。在繁忙的工作之余&#xff0c;人们希望能够找到一种既高效又真诚的交友方式。于是&#xff0c;线上交友平台成为了他们寻找爱情的新选择。让不同文化背景、不同工作…

动态规划<四> 回文串问题(含对应LeetcodeOJ题)

目录 引例 其余经典OJ题 1.第一题 2.第二题 3.第三题 4.第四题 5.第五题 引例 OJ 传送门Leetcode<647>回文子串 画图分析&#xff1a; 使用动态规划解决 原理&#xff1a;能够将所有子串是否是回文的信息保存在dp表中 在使用暴力方法枚举出所有子串&#xff0c;是…

突发!!!GitLab停止为中国大陆、港澳地区提供服务,60天内需迁移账号否则将被删除

GitLab停止为中国大陆、香港和澳门地区提供服务&#xff0c;要求用户在60天内迁移账号&#xff0c;否则将被删除。这一事件即将引起广泛的关注和讨论。以下是对该事件的扩展信息&#xff1a; 1. 背景介绍&#xff1a;GitLab是一家全球知名的软件开发平台&#xff0c;提供代码托…

一网多平面

“一网多平面”是一种网络架构概念&#xff0c;具体指的是在一张物理网络之上&#xff0c;逻辑划分出“1N”个平面。以下是对“一网多平面”的详细解释&#xff1a; 定义与构成 01一网多平面 指的是在统一的物理网络基础设施上&#xff0c;通过逻辑划分形成多个独立的网络平面…

shell脚本定义特殊字符导致执行mysql文件错误的问题

记得有一次版本发布过程中有提供一个sh脚本用于一键执行sql文件&#xff0c;遇到一个shell脚本定义特殊字符的问题&#xff0c;sh脚本的内容类似以下内容&#xff1a; # 数据库ip地址 ip"127.0.0.1" # 数据库密码 cmdbcmdb!#$! smsm!#$!# 执行脚本文件&#xff08;参…

R语言数据分析案例46-不同区域教育情况回归分析和探索

一、研究背景 教育是社会发展的基石&#xff0c;对国家和地区的经济、文化以及社会进步起着至关重要的作用。在全球一体化进程加速的今天&#xff0c;不同区域的教育发展水平呈现出多样化的态势。这种差异不仅体现在教育资源的分配上&#xff0c;还表现在教育成果、教育投入与…

我用Cursor+DeepSeek做了个飞书文档一键同步插件,免费使用!

作为一个飞书文档的重度使用者&#xff0c;我基本上都是先在飞书上写好文章&#xff0c;然后再想办法搬到其他平台上&#xff0c;所以对飞书一键同步有很强的需求。​ 于是我决定做个插件来支持飞书文档的同步。​ 说实话我是第一次玩插件&#xff0c;源代码看起来有些陌生&a…

【Qt】对象树(生命周期管理)和字符集(cout打印乱码问题)

1.对象树 对象树统一管理窗口内部控件的生命周期&#xff0c;本质是一颗多叉树。 new对象会加入到对象树中&#xff0c;窗口关闭/释放时统一销毁&#xff0c;不需要手动delete。 如果在栈上定义label对象&#xff0c;生命周期随构造函数&#xff0c;无法正常显示控件。 1.1演…

v3s点RGB屏 40pin 800x480,不一样的点屏,不通过chosen。

一、背景、目的、简介。 一般来说&#xff0c;通过uboot将屏幕参数传给kernel&#xff0c;是通过修改设备树。 uboot和kernel都需要屏幕点亮。uboot侧重于显示一张图片。而kernel则多是动画。 在这里&#xff0c;我先是找到了一个裸机点屏的代码。将其编译成静态库后&#x…

密码学期末考试笔记

文章目录 公钥加密之前的部分 (非重点&#xff0c;关注工具怎么用&#xff0c;和性质)一、对称加密 (symmetric ciphers)1. 定义 二、PRG (伪随机数生成器)1. 定义2. 属性 三、语义安全 (Semantic Security)1. one-time key2. 流密码是语义安全的 四、分组密码 (Block Cipher)1…