python-- socket 粘包、实现 ssh

简介: python-- socket 粘包、实现 ssh

粘包


只有tcp协议才会发送粘包,udp不会发生。发送端发送数据,接收端不知道应该如何去接收,造成的一种数据混乱的现象

import subprocess
r = subprocess.Popen('ls',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
# subprocess.Popen(cmd,shell=True,subprocess.stdout,subprocess.stderr)
# cmd : 代表系统命令
# shell = True   代表这条命令是 系统命令,告诉操作系统,将cmd当成系统命令去执行
# stdout   是执行完系统命令之后,用于保存结果的一个管道
# stderr   是执行完系统命令之后,用于保存错误结果的一个管道
stdout = r.stdout.read().decode('gbk')
stderr = r.stderr.read().decode('gbk')
print('正确的返回结果:',stdout)
print('错误的返回结果:',stderr)
print('错误的返回结果:',stderr)

客户端发送要执行命令

服务器执行,执行完将结果返回给客户端

客户端拿到结果呈现到用户眼前

服务端

import socket
import subprocess
sk = socket.socket()
sk.bind(('127.0.0.1', 8080))
sk.listen()
conn, addr = sk.accept()
while 1:
    cmd = conn.recv(1024).decode('utf-8')
    r = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout = r.stdout.read()
    stderr = r.stderr.read()
    if stderr:
        conn.send(stderr)
    else:
        conn.send(stdout)
conn.close()
sk.close()

客户端

import socket
sk = socket.socket()
sk.connect_ex(('127.0.0.1', 8080))
while 1:
    cmd = input('请输入一个命令>>>')
    sk.send(cmd.encode('utf-8'))
    result = sk.recv(102)
    result = result.decode('gbk')
    print(result)
sk.close()


socket 实现 ssh


a = '邹'
print(len(a))  # 1
print(len(a.encode()))  # 3  转换为bytes一个汉字三个字符

客户端

import socket
client = socket.socket()
client.connect(('localhost', 9999))
while True:
    msg = input(">>:").strip()
    if len(msg) == 0:  # 输入的为空
        continue
    client.send(msg.encode("utf-8"))
    data = client.recv(1024)
    print("recv:", data.decode())
client.close()

服务端

import socket, os
server = socket.socket()
server.bind(('localhost', 9999))
server.listen()
while True:
    conn, addr = server.accept()
    print('new conn', addr)
    while True:
        data = conn.recv(1024)
        if not data:
            print('客户端已断开')
            break
        print('执行指令:', data)
        cmd_res = os.popen(data.decode()).read()  # 执行输入的命令,decode转换为字符串
        if len(cmd_res) == 0:
            cmd_res = 'cmd has no out'
        conn.send(cmd_res.encode('utf-8'))  # 转为utf-8发过去

当我们在客户端执行 ifconfig 命令时,第一次返回的不全(1024字节),在执行 ls 命令时,返回的是 ifconfig 剩下的命令(1024字节),如下

>>:ifconfig
recv: lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
    options=1203<RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP>
    inet 127.0.0.1 netmask 0xff000000 
    inet6 ::1 prefixlen 128 
    inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 
    nd6 options=201<PERFORMNUD,DAD>
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280
ap1: flags=8802<BROADCAST,SIMPLEX,MULTICAST> mtu 1500
    options=400<CHANNEL_IO>
    ether b2:9c:4a:c4:34:e7 
    media: autoselect
    status: inactive
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    options=400<CHANNEL_IO>
    ether 90:9c:4a:c4:34:e7 
    inet6 fe80::18f2:9b2f:4496:675e%en0 prefixlen 64 secured scopeid 0x6 
    inet 192.168.31.110 netmask 0xffffff00 broadcast 192.168.31.255
    nd6 options=201<PERFORMNUD,DAD>
    media: autoselect
    status: active
p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304
    options=400<CHANNEL_IO>
    ether 02:9c:4a:c4:34:e7 
    media: autoselect
    status: inactive
awdl0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1484
    opti
>>:ls
recv: ons=400<CHANNEL_IO>
    ether e2:3f:ba:ac:28:1d 
    inet6 fe80::e03f:baff:feac:281d%awdl0 prefixlen 64 scopeid 0x8 
    nd6 options=201<PERFORMNUD,DAD>
    media: autoselect
    status: active
llw0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    options=400<CHANNEL_IO>
    ether e2:3f:ba:ac:28:1d 
    inet6 fe80::e03f:baff:feac:281d%llw0 prefixlen 64 scopeid 0x9 
    nd6 options=201<PERFORMNUD,DAD>
    media: autoselect
    status: active
en2: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
    options=460<TSO4,TSO6,CHANNEL_IO>
    ether 1e:66:6c:14:0d:c4 
    media: autoselect <full-duplex>
    status: inactive
en1: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
    options=460<TSO4,TSO6,CHANNEL_IO>
    ether 1e:66:6c:14:0d:c5 
    media: autoselect <full-duplex>
    status: inactive
en3: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
    options=460<TSO4,TSO6,CHANNEL_IO>
    ether 1e:66:6c:14:0d:c1 
    media: autoselect <full-duplex>
    status: inactive
en4: flags=8963<U


全部接收


先判断需要接收的数据,然后接收的和实际的对比,如果小于实际的,继续接收,否则,打印出接收的大小和命令

客户端

import socket
client = socket.socket()
client.connect(('localhost', 9999))
while True:
    msg = input(">>:").strip()
    if len(msg) == 0:
        continue
    client.send(msg.encode("utf-8"))
    data_size = client.recv(1024)  # 接收命令的长度
    print('需要接收的数据大小:', data_size)
    client.send('开始发吧'.encode('utf-8'))  # 处理黏包
    reve_size = 0
    reve_data = b''
    while reve_size < int(data_size.decode()):  # data_size是byte类型
        data = client.recv(1024)
        reve_size += len(data)  # 每次收到的有可能小于1024,所以必须用len判断
        reve_data += data
    else:
        print('接收到的大小:', reve_size)
        print(reve_data.decode())
client.close()

服务端

import socket, os
server = socket.socket()
server.bind(('localhost', 9999))
server.listen()
while True:
    conn, addr = server.accept()
    print('new conn', addr)
    while True:
        print('等待新指令')
        data = conn.recv(1024)
        if not data:
            print('客户端已断开')
            break
        print('执行指令:', data)
        cmd_res = os.popen(data.decode()).read()  # 执行输入的命令,decode转换为字符串
        print('数据的大小:', len(cmd_res))
        if len(cmd_res) == 0:
            cmd_res = 'cmd has no out'
        conn.send(str(len(cmd_res.encode())).encode('utf-8'))  # 数字不能encode。cmd_res.encode()将汉字转换成3个字节,不转发送的大小和接收的大小不一样
        conn.recv(1024)  # 处理黏包
        conn.send(cmd_res.encode('utf-8'))  # 转为 utf-8发过去

相关文章
|
20天前
|
安全 Java 数据处理
Python网络编程基础(Socket编程)多线程/多进程服务器编程
【4月更文挑战第11天】在网络编程中,随着客户端数量的增加,服务器的处理能力成为了一个重要的考量因素。为了处理多个客户端的并发请求,我们通常需要采用多线程或多进程的方式。在本章中,我们将探讨多线程/多进程服务器编程的概念,并通过一个多线程服务器的示例来演示其实现。
|
20天前
|
程序员 开发者 Python
Python网络编程基础(Socket编程) 错误处理和异常处理的最佳实践
【4月更文挑战第11天】在网络编程中,错误处理和异常管理不仅是为了程序的健壮性,也是为了提供清晰的用户反馈以及优雅的故障恢复。在前面的章节中,我们讨论了如何使用`try-except`语句来处理网络错误。现在,我们将深入探讨错误处理和异常处理的最佳实践。
|
21天前
|
网络协议 网络安全 Python
Python网络编程基础(Socket编程) 错误处理和异常
【4月更文挑战第10天】网络编程涉及到很多复杂的操作和潜在的风险,如连接失败、数据丢失、超时等问题。因此,正确的错误处理和异常捕获是确保网络程序稳定性和可靠性的关键。本章将介绍网络编程中常见的错误和异常,并探讨如何在Python中进行有效的错误处理。
|
21天前
|
存储 Python
Python网络编程基础(Socket编程) UDP 发送和接收数据
【4月更文挑战第10天】对于UDP客户端而言,发送数据是一个相对简单的过程。首先,你需要构建一个要发送的数据报,这通常是一个字节串(bytes)。然后,你可以调用socket对象的`sendto`方法,将数据报发送到指定的服务器地址和端口。
|
22天前
|
Python
Python网络编程基础(Socket编程)绑定地址和端口
【4月更文挑战第9天】在UDP服务器编程中,我们首先需要创建一个UDP套接字,然后绑定一个本地地址和端口,以便客户端可以通过这个地址和端口与我们的服务器进行通信。下面,我们将详细讲解如何绑定地址和端口。
|
23天前
|
网络协议 安全 网络安全
Python网络编程详解:Socket套接字的使用与开发
探索Python网络编程:本文详述Socket套接字,关键组件用于设备间通信。理解Socket类型(TCP/UDP),学习创建、绑定、监听、发送/接收数据步骤。示例展示服务端和客户端实现,及Socket聊天室应用。了解并发处理、错误处理和网络安全。通过学习,提升网络应用开发技能。参考书籍深入学习。
124 2
|
23天前
|
网络协议 Python
Python网络编程基础(Socket编程)创建UDP socket对象
【4月更文挑战第8天】在Python中创建UDP服务器涉及使用`socket`模块创建socket对象,如`udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)`,然后绑定到特定IP地址和端口,如`udp_socket.bind((&#39;localhost&#39;, 12345))`。服务器通过`recvfrom`在无限循环中监听和接收数据报。这只是基础,实际应用还需处理接收、解析、响应及错误处理等。接下来可学习如何利用socket对象进行数据交互以构建完整服务器。
|
23天前
|
网络协议 网络性能优化 开发者
Python网络编程基础(Socket编程)UDP Socket编程
【4月更文挑战第8天】Python网络编程中,UDP与TCP协议各有特点。TCP提供可靠连接,确保数据顺序与完整性,适合文件传输等;UDP则无连接,速度快,常用于实时音视频,牺牲了数据可靠性。Python的socket库支持两者,开发者可根据需求选择。
|
24天前
|
网络协议 Python
python中socket客户端发送和接收数据
【4月更文挑战第7天】本教程聚焦TCP客户端数据发送与接收。使用Python的`socket`模块,通过`send()`发送字节串至服务器,如`client_socket.send(message_bytes)`;用`recv()`接收数据,如`received_data = client_socket.recv(buffer_size)`。异常处理确保网络错误时程序健壮性,例如`try-except`捕获`socket.error`。理解和掌握这些基础操作对于构建稳定的TCP客户端至关重要。
|
7天前
|
存储 网络协议 关系型数据库
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信