网络编程基础【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 '\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的时候,不会发新数据,先把缓冲区剩下的数据发送到客户端。

如图:

 

转载于:https://www.cnblogs.com/luoahong/p/9896013.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值