python3套接字编程之socket和socketserver(TCP和UDP通信)

news2024/11/18 7:24:14

socket和socketserver是python3中socket通信模块,关于其使用做如下总结。

目录

1.socket

1.1模块引入

1.2套接字获取

1.3套接字接口

1.3.1 服务端

1.3.2 客户端套接字函数

1.3.3 公共套接字函数

1.3.4 面向锁的套接字方法

1.3.5 面向文件的套接字的函数

2.socketserver

3.TCP

3.1 socket类型TCP

3.2 socketserver类型TCP

4.UDP

3.1 socket类型UDP

3.2 socketserver类型UDP


1.socket

1.1模块引入

import socket

1.2套接字获取

接口:socket.socket(socket_family, socket_type, protocal=0)
参数:
    socket_family:AF_UNIX 或 AF_INET
    socket_type:SOCK_STREAM 或 SOCK_DGRAM
    protocol: 一般不填,默认值为 0
(1)tcp套接字
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
(2)udp套接字
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

1.3套接字接口

1.3.1 服务端

s.bind():绑定(主机,端口号)到套接字
s.listen():TCP监听
s.accept():接受TCP客户的连接

1.3.2 客户端套接字函数

s.connect():初始化TCP服务器连接
s.connect()
s.connect_ex():函数的扩展版本,出错时返回出错码,而不是抛出异常


1.3.3 公共套接字函数

s.recv():接收TCP数据
s.send():发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
s.sendall():发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
s.recvfrom():接收UDP数据
s.sendto():发送UDP数据
s.getpeername():连接到当前套接字的远端的地址
s.getsockname():当前套接字的地址
s.getsockopt():返回指定套接字的参数
s.setsockopt():设置指定套接字的参数
s.close():关闭套接字

1.3.4 面向锁的套接字方法

s.setblocking():设置套接字的阻塞与非阻塞模式
s.settimeout():设置阻塞套接字操作的超时时间
s.gettimeout():得到阻塞套接字操作的超时时间

1.3.5 面向文件的套接字的函数

s.fileno():套接字的文件描述符
s.makefile():创建一个与该套接字相关的文件

2.socketserver

socketserver是socket的升级版本,可以并发处理多个客户端的连接,其包含两个大类server类和request类,server类解决连接问题,request类解决通信问题
引用如下:
import socketserver

3.TCP

3.1 socket类型TCP

server.py

# -*- coding: UTF-8 -*-

import socket
from socket import SOL_SOCKET, SO_REUSEADDR
import subprocess
import struct
import json

PORT = 18284

#简单TCP通信
def main():
    tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print(tcpSocket)
    tcpSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    tcpSocket.bind(('127.0.0.1', PORT))
    tcpSocket.listen(5) 
    print('start....')
    while True:
        conn, client_addr = tcpSocket.accept()
        print('new client connected ', conn, client_addr)
        while True: 
            try:
                print('recv data ...')
                data = conn.recv(1024) 
                if len(data) == 0: 
                    break 
                print('recv data is ', data)
                conn.send(data.upper())
            except ConnectionResetError:
                break

    conn.close()
    phone.close()

#仿写ssh服务程序
def main1():
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(('127.0.0.1', PORT))
    server.listen(5)
    print('start...')
    while True:
        conn, client_addr = server.accept()
        while True:
            print('from client:', client_addr)
            cmd = conn.recv(1024)
            if len(cmd) == 0: 
                break
            print('cmd:', cmd)
            obj = subprocess.Popen(cmd.decode('utf8'), # 输入的cmd命令
                    shell=True, # 通过shell运行
                    stderr=subprocess.PIPE, # 把错误输出放入管道,以便打印
                    stdout=subprocess.PIPE) # 把正确输出放入管道,以便打印
 
            stdout = obj.stdout.read() # 打印正确输出
            stderr = obj.stderr.read() # 打印错误输出
 
            conn.send(stdout)
            conn.send(stderr)
        conn.close()
        server.close()

#自定义数据包
def main2():
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(('127.0.0.1', PORT))
    server.listen(5)
    print('start...')
    while True:
        conn, client_addr = server.accept()
        print(conn, client_addr)
        while True:
            cmd = conn.recv(1024)
            obj = subprocess.Popen(cmd.decode('utf8'),
                                    shell=True,
                                    stderr=subprocess.PIPE,
                                    stdout=subprocess.PIPE)
            stderr = obj.stderr.read()
            stdout = obj.stdout.read()
            print("stderr:", stderr)
            print("stdout:", stdout)
            data_dict = {
                'body_size': len(stdout) + len(stderr),
                'body': stderr.decode('utf-8') + stdout.decode('utf-8')
            }
            data_json = json.dumps(data_dict)
            data_bytes = data_json.encode('utf8')
            conn.send(struct.pack('i', len(data_bytes)))
            conn.send(data_bytes)
            conn.close()
            break
    server.close()


if __name__ == '__main__':
    main2()

client.py

# -*- coding: UTF-8 -*-

import socket
import json
import struct

PORT = 18284

def main():
    cs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    cs.connect(('127.0.0.1', PORT))
    while True: 
        msg = input('input data >>').strip() 
        if len(msg) == 0: 
            continue
        cs.send(msg.encode('utf-8'))
        data = cs.recv(1024)
        print(data)
    phone.close()


def main2():
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect(('127.0.0.1', PORT))
    while True:
        cmd = input('enter cmd >> ')
        if len(cmd) == 0: 
            continue
        #encode:字符串转字节数组
        client.send(cmd.encode('utf8'))
        data_len = struct.unpack('i', client.recv(4))[0]
        print("data_len: ", data_len)
        data_bytes = client.recv(data_len)
        print("data_bytes: ", data_bytes)
        #decode:字节数组转转字符串
        data_json = data_bytes.decode('utf8')
        print("data_json: ", data_json)
        data_dict = json.loads(data_json)
        print("data_dict: ", data_dict['body'])
        break
    client.close()
    
if __name__ == '__main__':
    main2()

运行效果如下:

 

 

3.2 socketserver类型TCP

server.py

# -*- coding: UTF-8 -*-

import socketserver

PORT = 18286

class MyHandler(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            print(self.client_address)
            print(self.request)
            try:
                data = self.request.recv(1024)
                if len(data) == 0: break
                self.request.send(data.upper())
            except ConnectionResetError:
                break
            
if __name__ == '__main__':
    s = socketserver.ThreadingTCPServer(('127.0.0.1', PORT), 
                                        MyHandler, 
                                        bind_and_activate=True)
    s.serve_forever()

client.py

# -*- coding: UTF-8 -*-

import socket

PORT = 18286

def main():
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect(('127.0.0.1', PORT)) 
    while True:
        msg=input('input msg >> ').strip()
        if len(msg) == 0: continue
        client.send(msg.encode('utf-8'))
        data = client.recv(1024)
        print(data.decode('utf-8'))
    client.close()

if __name__ == '__main__':
    main()

4.UDP

关于UDP,有如下需要注意:
(1)无连接的,先启动哪一端都不会报错,并且可以同时多个客户端去跟服务端通信
(2)数据报协议,发空的时候也会自带报头,因此客户端输入空,服务端也能收到,一般用于传输小数据
(4)无粘包问题,但是不能替代TCP套接字,因为UPD协议有一个缺陷:如果数据发送的途中,数据丢失,则数据就丢失了,而TCP协议则不会有这种缺陷,因此UPD套接字多用于无关紧要的数据发送,例如IM聊天工具

3.1 socket类型UDP

server.py

# -*- coding: UTF-8 -*-

import socket

PORT = 18285

def main():
    server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server.bind(('127.0.0.1', PORT))
    while True:
        data, client_addr = server.recvfrom(1024)
        print('recvfrom:', data, client_addr)
        server.sendto(data.upper(), client_addr)
    server.close()

if __name__ == '__main__':
    main()

client.py

# -*- coding: UTF-8 -*-

import socket

PORT = 18285

def main():
    client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    while True:
        msg = input('input >> ').strip()
        client.sendto(msg.encode('utf-8'), ('127.0.0.1', PORT))
        data, server_addr = client.recvfrom(1024)
        print(data, data.decode('utf-8'))
    client.close()

if __name__ == '__main__':
    main()


3.2 socketserver类型UDP

基于udp的socketserver自己定义的类,其中
self.request是一个元组(第一个元素是客户端发来的数据,第二部分是服务端的udp套接字对象)
self.client_address即客户端地址

server.py

# -*- coding: UTF-8 -*-

import socketserver

PORT = 18287

class MyHandler(socketserver.BaseRequestHandler):
    def handle(self):
        print(self.client_address)
        print(self.request)
        data = self.request[0]
        print('client msg:', data)
        self.request[1].sendto(data.upper(), self.client_address)
        
if __name__ == '__main__':
    s = socketserver.ThreadingUDPServer(('127.0.0.1', PORT), MyHandler)
    s.serve_forever()

client.py

# -*- coding: UTF-8 -*-

import socket

PORT = 18287

def main():
    client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    while True:
        msg=input('input >> ').strip()
        client.sendto(msg.encode('utf-8'), ('127.0.0.1', PORT))
        data, server_addr = client.recvfrom(1024)
        print(data)
    client.close()

if __name__ == '__main__':
    main()

运行效果如下:

 

 

 

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

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

相关文章

Python注释解密、变量大揭秘,数据类型轻松入门!

文章目录 前言注释单行注释多行注释 变量数据类型1.整型(int)2.浮点型(float)3.布尔型(bool)4.字符串(str)5.列表(list)6.元组(tuple)…

RabbitMQ高可用集群部署

文章目录 1.RabbitMQ常见的集群模式2.部署基于镜像队列模式的RabbitMQ高可用集群2.1.镜像队列集群原理2.2.分别在两台机器中部署RabbitMQ2.2.1.基础环境配置2.2.2.安装Erlang环境2.2.3.部署RabbitMQ并开启管理界面2.2.4.配置RabbitMQ各节点变量信息2.2.5.访问RabbitMQ后台管理系…

vue3基础------ 下

目录 二.vue3基础 5.事件处理器 5-1 事件处理器 - 告别原生事件 5-2 事件修饰符 - 事件偷懒符? 6.表单控件绑定 6-1表单输入绑定-一根绳上的蚂蚱 6-2购物车案例 6-3表单修饰符 7.计算属性 7-1计算属性-很聪明,会缓存 7-2 可写计算属性 7-3之前案例的小改…

ModaHub魔搭社区:向量数据库MIlvus服务端配置(三)

目录 gpu 区域 logs 区域 metric_config 区域 gpu 区域 在该区域选择是否在 Milvus 里启用 GPU 用于搜索和索引创建。同时使用 CPU 和 GPU 可以达到资源的最优利用,在特别大的数据集里做搜索时性能更佳。 若要切换到 CPU-only 模式,只要将 enable 设…

【敬伟ps教程】色彩基础

文章目录 在通道内发现色光吸管工具与颜色面板在RGB通道创造色彩色彩三要素选择方式CMYK模式详解 在通道内发现色光 RGB基于色光的混合模式,是最常见的色彩模式 我们新建一个 RGB 画布,前景色改为黑色,AltDelete填充前景色。我们查看图像–…

实验篇(7.2) 18. 星型安全隧道 - 分支互访(IPsec) ❀ 远程访问

【简介】Hub-and-Spoke:各分支机构利用VPN设备与总部VPN设备建立VPN通道后,除了可以和总部进行通讯,还可以利用总部VPN设备互相进行数据交换,而各VPN分支机构不需要进行VPN的隧道连接。 实验要求与环境 OldMei集团深圳总部部署了域…

C# 线程基础 二

目录 八、前台线程和后台线程 九、线程参数的传递 十、线程中的 lock 关键字 十一、Monitor类锁定 结束 八、前台线程和后台线程 默认情况下,显式创建的线程是前台线程,通过手动的设置 Thread 类的属性 IsBackground true 来指示当前线程为一个后…

让GPT-3、ChatGPT、GPT-4一起做脑筋急转弯,GPT-4一骑绝尘!

作者 | python 一个烙饼煎一面一分钟,两个烙饼煎两面几分钟? 让你来回答,是不是一不小心就掉到沟里了?如果让大语言模型来做这种脑筋急转弯会怎样呢?研究发现,模型越大,回答就越可能掉到沟里&a…

VScode连接远程服务器

VScode连接远程服务器 文章目录 VScode连接远程服务器下载扩展通过扩展连接服务器在输入框中输入usernameip进行连接通过已保存的配置信息进行连接 连接成功之后访问服务器文件访问文件 下载扩展 下载以下三个扩展 Remote-SSH Remote - SSH: Editing Configuration Files R…

Docker Network 基础

一、是什么 Docker网络是Docker容器之间和容器与外部网络之间的通信和连接的一种机制。在Docker中,每个容器都可以有自己的网络栈,包括网络接口、IP地址和网络配置。Docker网络提供了一种灵活且可定制的方式,使得容器之间可以相互通信&#x…

【单元测试】Junit 4(二)--eclipse配置Junit+Junit基础注解

目录 1.0 前言 1.1 配置Junit 4 1.1.1 安装包 1.1.2 创建Junit项目 1.2 Junit 4 注解 1.2.1 测试用例相关的注解 1.2.1.1 Before 1.2.1.2 After 1.2.1.3 BeforeClass 1.2.1.4 AfterClass 1.2.1.5 Test 1.2.1.6 Ignore 1.2.1.7 示例 1.2.2 打包测试Suite相关的注解…

JAVA工程打包

目录 一、工程代码和第三方依赖包分开 二、工程代码和第三方依赖包打入同一个jar包 1、工程的class文件和依赖的第三方jar包所包含的class文件打进同一个jar包中。部署时,直接部署该jar包即可。 2、如果是springboot工程,可以将工程的class文件和依赖…

iOS多语言解决方案全面指南

本文以及相关工具和代码旨在为已上线的iOS项目提供一种快速支持多语言的解决方案。由于文案显示是通过hook实现的,因此对App的性能有一定影响;除了特殊场景的文案显示需要手动支持外,其他任务均已实现自动化。 本文中的部分脚本代码基于 Chat…

OpenShift 4 - 可观测性之用 Network Observability Operator 对网络流量进行监控观测(视频)

《OpenShift / RHEL / DevSecOps 汇总目录》 说明:本文已经在支持 OpenShift 4.12 Loki Operator 5.7.2 Network observability 1.2.0 的环境中验证 文章目录 Network Observability 相关组件和架构安装 Network Observaility 功能安装 Operator配置对象存储配置 …

Scrapy的基本使用

目录 Scrapy是什么 安装 使用 获取更多页面信息 写入数据库 图片下载 文件下载 更改文件名称以及路径 更改图片名称以及路径 循环获取页面信息时,item的数据重复或者对不上 下载文件时获取文件流直接上传到某个地方 Scrapy是什么 Scrapy 是一个基于 Pyth…

园区自然人代开果真那么好?可以解决成本票缺失吗?

园区自然人代开果真那么好?可以解决成本票缺失吗? 《税筹顾问》专注于园区招商、企业税务筹划,合理合规助力企业节税! 自然人代开也就是指个人跟公司发生业务往来的时候,公司要求个人开具发票,进行入账&am…

open-mmlab/mmocr 环境搭建、推理和训练入门教程【一】

文章目录 博文基础信息Linux 搭建 open-mmlab/mmocr 运行环境准备数据集准备必要的预训练模型推理训练测试可视化输出 📙 预祝各位 前途似锦、可摘星辰 博文基础信息 https://mmocr.readthedocs.io/zh_CN/dev-1.x/get_started/quick_run.html显卡,11G 1…

【Pytorch】梯度裁剪——torch.nn.utils.clip_grad_norm_的原理及计算过程

文章目录 一、torch.nn.utils.clip_grad_norm_二、计算过程三、确定max_norm 众所周知,梯度裁剪是为了防止梯度爆炸。在训练FCOS算法时,因为训练过程出现了损失为NaN的情况,在github issue有很多都是这种训练过程出现loss为NaN,作…

RISCV Reader笔记_3 RISCV汇编

RISC-V 汇编语言 函数调用的步骤在计算机组成与设计中也有过涉及: 指定寄存器存入参数;跳转到函数开始位置(jal);在callee中按需保存寄存器;执行函数;恢复保存的寄存器;把返回值存入…

使用传统图像处理算法+机器学习进行shadow detection

前言 阴影是图像中常见的现象,它们对于场景理解和分析非常重要。由于阴影区域通常比较暗淡,而且与周围物体区别较大,因此在图像处理和计算机视觉领域中,阴影检测是一个重要的研究方向。传统的阴影检测算法通常基于阈值或边缘检测…