本节内容

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'\xe5\xb0\x8f\xe9\xab\x98\xe6\x9c\x80\xe5\xb8\x85\xe4\xba\x86'  #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'\xe5\xb0\x8f\xe9\xab\x98\xe6\x9c\x80\xe5\xb8\x85\xe4\xba\x86'  #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的时候,不会发新数据,先把缓冲区剩下的数据发送到客户端。

如图:

网络编程基础【day09】:通过socket实现简单ssh客户端(三)的更多相关文章

  1. 第1章 网络编程基础(3)——基本Socket通信

    服务器常用模型

  2. python学习之路---day25( 网络编程基础和初识socket)

    基本网络知识和初识socket一:基本知识 网线:传输电信号 集线器:将所有连接到集线器的网络设备连通起来 交换机: 升级版的集线器 网卡:接受电信号 MAC地址:物理地址: 8C-88-4B-88- ...

  3. 网络编程基础——System.Net.Socket 命名空间及相关类的使用

    System.Net.Socket 命名空间主要提供制作 Socket 网络应用程序的相关类.(Socket 类.TcpClient 类.TcpListener 类 和 UdpClient 类) 1. ...

  4. 第5章 Linux网络编程基础

    第5章 Linux网络编程基础 5.1 socket地址与API 一.理解字节序 主机字节序一般为小端字节序.网络字节序一般为大端字节序.当格式化的数据在两台使用了不同字节序的主机之间直接传递时,接收 ...

  5. Android 网络编程基础之简单聊天程序

    前一篇讲了Android的网络编程基础,今天写了一个简单的聊天程序分享一下 首先是服务端代码: package com.jiao.socketdemo; import java.io.Buffered ...

  6. python全栈开发从入门到放弃之socket网络编程基础

    网络编程基础 一 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务 ...

  7. Linux高并发网络编程开发——10-Linux系统编程-第10天(网络编程基础-socket)

    在学习Linux高并发网络编程开发总结了笔记,并分享出来.有问题请及时联系博主:Alliswell_WP,转载请注明出处. 10-Linux系统编程-第10天(网络编程基础-socket) 在学习Li ...

  8. C#网络编程基础知识

    C#网络编程基础知识一 1.IPAddress类 用于表示一个IP地址.IPAddress默认构造函数 public IPAddress(long address);一般不用 其中Parse()方法最 ...

  9. 用Netty开发中间件:网络编程基础

    用Netty开发中间件:网络编程基础 <Netty权威指南>在网上的评价不是很高,尤其是第一版,第二版能稍好些?入手后快速翻看了大半本,不免还是想对<Netty权威指南(第二版)&g ...

随机推荐

  1. 基准对象object中的基础类型----列表 (四)

    object有如下子类: CLASSES object basestring str unicode buffer bytearray classmethod complex dict enumera ...

  2. Android环境搭建(大学授课课件)

    前面一直没有提过如何搭建Android开发环境,其实这些网上一大堆,随便一搜就是很多大神的详细介绍.本人过于懒惰,拿出大学授课课件供大家参考.非原创 位)   下载地址: sdk:http://pan ...

  3. Pleasant sheep and big big wolf HDU - 3046(最小割)

    Pleasant sheep and big big wolf Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 ...

  4. 【ARC072E】Alice in linear land DP

    题目大意 有一个人要去直线上\(lm\)远处的地方,他会依次给他的机器发出\(n\)个指令.第\(i\)个指令为\(d_i\).他的机器收到一个指令\(x\)后,如果向目的地方向前进\(xm\)后比当 ...

  5. 【AtCoder3611】Tree MST(点分治,最小生成树)

    [AtCoder3611]Tree MST(点分治,最小生成树) 题面 AtCoder 洛谷 给定一棵\(n\)个节点的树,现有有一张完全图,两点\(x,y\)之间的边长为\(w[x]+w[y]+di ...

  6. Codeforces | CF1028C 【Rectangles】

    (这道题太简单啦...虽说我锤了一上午都没过...我能说这道题和\(CF1029C\)算是同一道题吗...) 按照时间顺序来说...\(CF1029\)在\(CF1028\)前面(而且\(CF1029 ...

  7. 「SCOI2016」围棋 解题报告

    「SCOI2016」围棋 打CF后困不拉基的,搞了一上午... 考虑直接状压棋子,然后发现会t 考虑我们需要上一行的状态本质上是某个位置为末尾是否可以匹配第一行的串 于是状态可以\(2^m\)压住了, ...

  8. [HNOI2015]落忆枫音 解题报告

    [HNOI2015]落忆枫音 设每个点入度是\(d_i\),如果不加边,答案是 \[ \prod_{i=2}^nd_i \] 意思是我们给每个点选一个父亲 然后我们加了一条边,最后如果还这么统计,那么 ...

  9. cf1000F One Occurrence (线段树)

    这题我是离线做的 设i位置的数上次出现的位置是pre[i](如果第一次出现那就是0) 可以想到,用线段树维护一个区间的pre的最小值,如果它小于区间左端点,那这个数就是一个合法的答案 但直接这样做是错 ...

  10. PHP函数memory_get_usage获取PHP内存清耗量

    (PHP 4 >= 4.3.2, PHP 5, PHP 7) memory_get_usage — 返回分配给 PHP 的内存量 说明 int memory_get_usage ([ bool ...