zoukankan      html  css  js  c++  java
  • 网络编程基础【day09】:通过socket实现简单ssh客户端(三)

    本节内容

    1、概述

    2、socket发送中文

    3、重复发送和多次接收

    4、模拟ssh客户端

    一、概述

      本篇博客讲一下,如果socket客户端断了,另外的客户端怎么接入服务端,还有模拟ssh的链接等。

    二、socket发送中文

      因为在python 3中只能接受bytes类型的数据,bytes类型只能接受ASCII码里面的数据类型。因为bytes类型是一个ASCII 0-255的数字组合。所以在客户端向服务端传中文时一定要先转成bytes类型,也就是encode(),接收方需要解码,也就是decode()才能识别中文。

    2.1、发送中文代码

    ①客户端

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import  socket
     
    client = socket.socket()
    client.connect(("localhost",6969))
    msg = "小高最帅了"
    client.send(msg.encode())  #传中文至服务端,需要先编码
    server_data  = client.recv(1024)
    print("recv:",server_data)   #未解码
    print("recv:",server_data.decode())   #解码
    client.close()
     
    #输出
    recv: b'xe5xb0x8fxe9xabx98xe6x9cx80xe5xb8x85xe4xbax86'  #bytes类型
    recv: 小高最帅了   #字符串

     ②服务端

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import socket
     
    sever = socket.socket()
    sever.bind(("127.0.0.1",6969))  #绑定ip地址和端口
    sever.listen()   #监听
    conn,address = sever.accept()   #获取接收实例和ip地址
    print("电话来了")
    client_data = conn.recv(1024)   #接收客户端数据
    print("recv:",client_data)
    print("recv:",client_data.decode())
    conn.send(client_data)   #发送给客户端
     
    sever.close()
     
    #输出
    电话来了
    recv: b'xe5xb0x8fxe9xabx98xe6x9cx80xe5xb8x85xe4xbax86'  #bytes类型
    recv: 小高最帅了   #解码后的结果

    注意了:所有的数据发送和接收都用bytes类型就可以了,省的有什么异常情况。

    三、重复发送和多次接收

      上面的代码只能客户端只能发送一次,服务端接收一次,就这么结束了,感觉很不爽,那怎么实现客户端发送多次,服务端接收多次呐?

    3.1、重复发送和多次接收代码

    ①客户端

    说明:客户端在发送处设置死循环(while  True),实现重复发送。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import  socket
     
    client = socket.socket()
    client.connect(("localhost",6969))
     
    while True:    #进入死循环,设置无限次发送
        msg = input(">>>:")
        client.send(msg.encode())
        data  = client.recv(1024)
        print("recv:",data.decode())
     
    client.close()

    ②服务端

    说明:服务端在接收时,设置死循环,实现重复接收。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import socket
     
    sever = socket.socket()
    sever.bind(("127.0.0.1",6969))
    sever.listen()
    conn,address = sever.accept()   #接收连接实例
    print("电话来了")
    while True:   #设置死循环,接收多次
        data = conn.recv(1024)
        print("recv:",data.decode())
        conn.send(data)
     
    sever.close()

     注:这边注意了,在服务端,while True千万不能写在conn,address = sever.accept()前面,这个是为什么呢?因为客户端跟服务端只能实现建立一个连接,如果你把while True放在前面,则服务端接收数据后,又要重新建立一个新的等待连接,这样,客户端和服务端都会卡主。

    服务端的代码如下:

     表现现象:

    3.2、处理多个链接

    说明:我们在客户端一起链接服务端,我们都知道,一个服务端只能跟一个客户端进行链接通信,那如果说,我这个正在通信的客户端断开跟服务端的通信,那其他的某个客户端就能跟客户端正常通信了,这个实验一定要在Linux服务器上去完成,因为在Windows上就是只要客户端一断开,服务端就断开了。

    跟上面一样,客户端的代码没有变,我们现在来变一下服务端的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import socket
     
    sever = socket.socket()
    sever.bind(("127.0.0.1",6969))
    sever.listen()
    while True#在建立连接之前加一个死循环
        conn,address = sever.accept()
        print("电话来了")
      count = 0   #加一个计数器
        while True:
            data = conn.recv(1024)
         if not data:break   #这边如果接受客户端数据为空,则重新建立连接
            print("recv:",data.decode())
            conn.send(data)
         count += 1
     
    sever.close()

    注意:上面if not data:break这段代码不写的后果是:当客户端断开链接时,服务端进入死循环,不断接收客户端的空数据。

     现象如图:

    ①客户端

    ②服务端

    3.3、 客户端发送数据为空

    说明:我们之前演示都是客户端输入内容,服务端给出相应,那客户端输入的是空的话,服务端会有什么反映呐?

    客户端代码如图:

    服务端代码跟上面的一样,执行结果如下:

    客户端:

    服务端:

    原因是:客户端输入的为空,服务端还一直以为客户端在send,然后都卡主了。

    那代码怎么改进呢?代码改进如下:

    客户端代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import  socket
     
    client = socket.socket()
    client.connect(("localhost",6969))
     
    while True:
        msg = input(">>>:")
        if len(msg) == 0:continue   #这边判断输入的字符是否为空,为空就跳过
        client.send(msg.encode())
        data  = client.recv(1024)
        print("recv:",data.decode())
     
    client.close()

    表现现象:

    客户端:

    服务端:

    四、模拟ssh客户端

    4.1、模拟ssh访问

    说明:以下代码,是在Linux下环境,而且还是python2.7的环境,如果是python 3的话,需要编码和解码。

    ①客户端

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #! /usr/bin/env python
    # -*- coding:utf-8 -*-
     
    import  socket
     
    client = socket.socket()
    client.connect(("localhost",6969))
     
    while True:
        msg = raw_input(">>>:")
        if len(msg) == 0:continue
        client.send(msg)
        data  = client.recv(1024)
        print(data)
     
    client.close()

    ②服务端

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #! /usr/bin/env python
    # -*- coding:utf-8 -*-
     
    import socket,os   #导入os模块
     
    sever = socket.socket()
    sever.bind(("127.0.0.1",6969))
    sever.listen(5)  #最大允许有多少个链接
    while True:
        conn,address = sever.accept()
        print("电话来了")
        count = 0
        while True:
            data = conn.recv(1024)
            if not data:break
            res = os.popen(data).read()   #调用linux命令
            conn.send(res)   #执行的命令返回值
     
    sever.close()

    注:conn.send(res)这边如果需要发送全部的话,需要conn.sendall(res)

    4.2、下载文件

    ①客户端

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import  socket
     
    client = socket.socket()
    client.connect(("localhost",6969))
    while True:
        msg = input(">>>:")
        if len(msg) == 0:continue
        client.send(msg.encode())
        data  = client.recv(1024000)   #这边设置的大一点,防止文件的内容接收不到
        with open("test_put","wb") as test_put_file:   #把下载下来的内容写入到文件中
            test_put_file.write(data)
     
    client.close()

     ②服务端

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import socket
     
    sever = socket.socket()
    sever.bind(("127.0.0.1",6969))
    sever.listen()
    conn,address = sever.accept()
    print("电话来了")
    while True:
        data = conn.recv(1024)
        if not data:
            print("数据为空")
            break
        with open("test","rb") as test_file:
            all_data_bytes = test_file.read()   #读取需要下载的文件,发送给客户端
        conn.sendall(all_data_bytes)
     
    sever.close()

    注意:这边客户端的接收时有限制的,如果超出了客户端的限制,客户端只接收自己的一部分,而剩余的会在还是在缓冲去,下一次服务端再send的时候,不会发新数据,先把缓冲区剩下的数据发送到客户端。

    如图:

  • 相关阅读:
    selenium——上传文件
    selenium——下拉框
    selenium——鼠标操作ActionChains:点击、滑动、拖动
    selenium定位元素—逻辑运算、xpath函数、轴定位
    spring设置webAppRootKey
    树莓3 集群
    redis集群搭建
    MQ基础
    MQ集群测试环境搭建(多节点负载均衡,共享一个kahaDB文件(nas方式))
    weblogic对jms实现的QueueConnection实现与TopicConnection实现问题
  • 原文地址:https://www.cnblogs.com/luoahong/p/9896013.html
Copyright © 2011-2022 走看看