python网络编程

使用网络编程编写一个类似ssh的应用

客户端

#!/usr/bin/python3
import socket
import struct
import sys
import time
import argparse

# 创建解析对象
parser = argparse.ArgumentParser()

# 添加命令行参数、选项
parser.add_argument(
    "-c",
    "--client",
    default="127.0.0.1",
    help="run in client mode, connecting to <host>",
)

parser.add_argument(
    "-p",
    "--port",
    default=8888,
    help="server port to listen on/connect to",
)


# 进行解析
args = parser.parse_args()

IP_ADDRESS = (args.client, args.port)
BUF_SIZE = 1024
try:
    client =socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    client.connect_ex(IP_ADDRESS)
    while True:
        cmd = input("tcp>").strip()
        if not cmd:
            continue
        client.send(cmd.encode("utf-8"))
        res_header = client.recv(4)
        total_size = struct.unpack("i", res_header)[0]
        recv_size = 0
        while recv_size < total_size:
            res = client.recv(BUF_SIZE)
            recv_size += len(res)
            sys.stdout.write(res.decode("utf-8"))
        sys.stdout.write("\n")
except KeyboardInterrupt:
    print("\n断开连接\n")
except Exception as e:
    print(e)

服务端

单客户端连接

#!/usr/bin/python3
import sys
import struct
import socket
import subprocess
import argparse

# 创建解析对象
parser = argparse.ArgumentParser()

# 添加命令行参数、选项
parser.add_argument(
    "-s",
    "--server",
    default="",
    help="run in server mode",
)

parser.add_argument(
    "-p",
    "--port",
    default=8888,
    help="server port to listen on/connect to",
)


# 进行解析
args = parser.parse_args()

IP_ADDRESS = (args.server, args.port)
BUF_SIZE = 1024
try:
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(IP_ADDRESS)
    server.listen(5)
    while True:
        conn, addr = server.accept()
        while True:
            try:
                cmd = conn.recv(BUF_SIZE)
                if not cmd:
                    break
                obj = subprocess.Popen(cmd.decode('utf-8'),
                                    shell=True,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
                res_stdout = obj.stdout.read()
                res_stderr = obj.stderr.read()
                res_len = len(res_stdout) + len(res_stderr)
                # 制作TCP头,利用struct的模块的pack将返回内容的长度打包成4个byte发送
                res_header = struct.pack('i', res_len)
                # 利用TCP流式传输的特性
                conn.send(res_header)
                conn.send(res_stdout)
                conn.send(res_stderr)
            except Exception as e:
                sys.stderr.write(f'error message:{e}')
        conn.close()
except KeyboardInterrupt:
    print()

多客户端连接(多线程)

#!/usr/bin/python3
import sys
import struct
import socketserver
import subprocess
import argparse

# 创建解析对象
parser = argparse.ArgumentParser()

# 添加命令行参数、选项
parser.add_argument(
    "-s",
    "--server",
    default="",
    help="run in server mode",
)

parser.add_argument(
    "-p",
    "--port",
    default=8888,
    help="server port to listen on/connect to",
)


# 进行解析
args = parser.parse_args()

IP_ADDRESS = (args.server, args.port)
BUF_SIZE = 1024
class MyRequestHandler(socketserver.BaseRequestHandler):
    def handle(self):
        """
        TCP中的conn-->self.request
        TCP中的addr-->self.client_address
        """
        while 1:
            try:
                cmd = self.request.recv(BUF_SIZE)
                if not cmd: break
                obj = subprocess.Popen(cmd.decode('utf-8'),
                                       shell=True,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE)
                res_stdout = obj.stdout.read()
                res_stderr = obj.stderr.read()
                # 将报头的长度进行打包
                res_header = struct.pack('i', len(res_stdout) + len(res_stderr))
                # 利用TCP流式传输特性
                self.request.send(res_header)
                self.request.send(res_stdout)
                self.request.send(res_stderr)
            except Exception as e:
                sys.stderr.write(f'error message:{e}')
        self.request.close()


try:
    s = socketserver.ThreadingTCPServer(IP_ADDRESS, MyRequestHandler)
    s.serve_forever()
except KeyboardInterrupt:
    s.server_close()
    print()

多客户端连接(协程)

#!/usr/bin/python3
from gevent import monkey, spawn
monkey.patch_all()
import socket
import sys
import struct
import subprocess
import argparse

# 创建解析对象
parser = argparse.ArgumentParser()

# 添加命令行参数、选项
parser.add_argument(
    "-s",
    "--server",
    default="",
    help="run in server mode",
)

parser.add_argument(
    "-p",
    "--port",
    default=8888,
    help="server port to listen on/connect to",
)


# 进行解析
args = parser.parse_args()

IP_ADDRESS = (args.server, args.port)
BUF_SIZE = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
server.bind(IP_ADDRESS)
server.listen(5)
def Server(conn):
        while True:
            try:
                cmd = conn.recv(BUF_SIZE)
                if not cmd: break
                obj = subprocess.Popen(cmd.decode('utf-8'),
                                    shell=True,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
                res_stdout = obj.stdout.read()
                res_stderr = obj.stderr.read()
                res_len = len(res_stdout) + len(res_stderr)
                # 制作TCP头,利用struct的模块的pack将返回内容的长度打包成4个byte发送
                res_header = struct.pack('i', res_len)
                # 利用TCP流式传输的特性
                conn.send(res_header)
                conn.send(res_stdout)
                conn.send(res_stderr)
            except Exception as e:
                sys.stderr.write(f'error message:{e}')
        conn.close()
try:
    while True:
        conn, addr = server.accept()
        spawn(Server, conn)
except KeyboardInterrupt:
    server.close()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值