解决网络编程中的一个字符编码问题(模拟ssh远程执行命令)

目录

一.操作系统导致的编码问题

1.程序实现

2.错误分析

3.错误解决

二.总结


  我今天实在是太开心了,我在学习了网络编程以后发现,不会的东西越来越多了,听的知识点也有点模糊,今天在碰到了一个比较有趣的字符编码和操作系统的问题,刚刚解决,太开心了兄弟们,那一刻我差点飞上天好吗。这里我看的视频全都是b站路飞学城的,视频也讲得很好,建议大家一起学习

一.操作系统导致的编码问题

我们知道,最常用的操作系统有windows,linux/unix ,mac os等,而mac os 其实就是基于unix开发的,所以mac os在操作方式上与linux相似,这里我们需要知道,既然操作系统不同,里面默认编码也会有所不同,大家现在来看看网络编程中这样一个服务端与客户端交互的问题

1.程序实现

这段程序的需求是这样,实现服务端和客户端的一个通信,已经加上了通信循环和连接循环,现在要求实现ssh的远程命令,相当于客户端传入的是关于本机的命令来查看本机的信息(也就是windows中的docs命令)

2.错误分析

  在刚开始看视频学习完这段代码的时候,出了很多错误,比如下面这些,但是全部都不要管,不要在csdn上搜问题这些问题,因为我在csdn上搜了大多是关于外部库的问题,但是到头来才发现这全都是自己的代码出了问题

解决网络编程中的一个字符编码问题(模拟ssh远程执行命令)_第1张图片解决网络编程中的一个字符编码问题(模拟ssh远程执行命令)_第2张图片 

 下面我们来看看up主在mac上写的代码

#-------------------------服务端---------------------------

import socket
import subprocess
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)  #判断接口是否被占用
phone.bind(("172.20.10.4",3237))
phone.listen(5)   
print("starting")
while True:       
    conn,client_add = phone.accept()
    print(client_add)

    while True:
        try:
            #1.收命令
            cmd=conn.recv(1024)        
            if not cmd:break
            #2.执行命令,拿到结果
            obj = subprocess.Popen(cmd.decode("utf-8"), shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
            stdout = obj.stdout.read()
            stderr = obj.stderr.read()
            #3.把命令的结果返回给客户端
            conn.send(stdout + stderr)
        except ConnectionResetError :
            break
    conn.close()

phone.close()
#------------------------------------客户端------------------------

import socket

phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(("172.20.10.4",3237))

while True:
    #1.发命令
    cmd = input(">>>: ").strip()   
    if not cmd: continue          
    phone.send(cmd.encode("utf-8"))
    #2.拿到命令的结果并打印
    data=phone.recv(1024)
    print(data.decode("utf-8"))

phone.close()

因为我们已经导入了数据库subprocess,里面用管道把数据存储下来的时候,就是用字节来存储的,所以我们需要在客户端打印的时候进行解码,这是up主说服务端拿到的stdout + stderr 在他的电脑上是linux系统上,执行命令的结果,所以服务端是用utf-8发的,所以解码也要用utf-8进行解码,如果你是服务端在windows操作系统上,服务端发送stdout + stderr数据是用gbk编码的,所以要把客户打印结果中的解码类型变成jbk,但是我改了,程序可以运行一次,但是仍然会报错,说什么我的远程主机中的软件中止了一个已建立的项目

3.错误解决

这时我把我所有的utf-8改成了gbk,就可以运行了,这里也可能是我对up主讲的话有点误解,没有将全部的utf-8改为jbk导致的

我同时也查了一下,windows上默认的字符编码是gbk,而我在代码中写的,需要将客户端传给服务端运行的东西,全部都是字节,所以不止是最后打印的时候需要解码,而是只要服务端接收了客户端的命令就需要解码

二.总结

这一次遇到的字符编码的问题与我第一次写的文章中的字符编码的问题相对应了,虽然这样不只是字符编码的全部,但我相信在深入的学习以后,我会将以前所有不太清楚的语法一一完善

你可能感兴趣的