Python学习记录之----网络通讯(二)

 

网络通讯   sockethtml

这一节太难了,仍是看TA的吧linux

http://www.cnblogs.com/alex3714/articles/5830365.htmlshell

 

  1. 不能执行top等相似的 会持续输出的命令,这是由于,服务器端在收到客户端指令后,会一次性经过os.popen执行,并获得结果后返回给客户,但top这样的命令用os.popen执行你会发现永远都不会结束,因此客户端也永远拿不到返回。(真正的ssh是经过select 异步等模块实现的,咱们之后会涉及)
  2. 不能执行像cd这种没有返回的指令, 由于客户端每发送一条指令,就会经过client.recv(1024)等待接收服务器端的返回结果,可是cd命令没有结果 ,服务器端调用conn.send(data)时是不会发送数据给客户端的。 因此客户端就会一直等着,等到天荒地老,结果就卡死了。解决的办法是,在服务器端判断命令的执行返回结果的长度,若是结果为空,就本身加个结果返回给客户端,如写上"cmd exec success, has no output."
  3. 若是执行的命令返回结果的数据量比较大,会发现,结果返回不全,在客户端上再执行一条命令,结果返回的仍是上一条命令的后半段的执行结果,这是为何呢?这是由于,咱们的客户写client.recv(1024), 即客户端一次最多只接收1024个字节,若是服务器端返回的数据是2000字节,那有至少9百多字节是客户端第一次接收不了的,那怎么办呢,服务器端此时不能把数据直接扔了呀,so它会暂时存在服务器的io发送缓冲区里,等客户端下次再接收数据的时候再发送给客户端。 这就是为何客户端执行第2条命令时,却接收到了第一条命令的结果的缘由。 这时有同窗说了, 那我直接在客户端把client.recv(1024)改大一点不就行了么, 改为一次接收个100mb,哈哈,这是不行的,由于socket每次接收和发送都有最大数据量限制的,毕竟网络带宽也是有限的呀,不能一次发太多,发送的数据最大量的限制 就是缓冲区能缓存的数据的最大量,这个缓冲区的最大值在不一样的系统上是不同的, 我实在查不到一个具体的数字,但测试的结果是,在linux上最大一次可接收10mb左右的数据,不过官方的建议是不超过8k,也就是8192,而且数据要能够被2整除,不要问为何 。anyway , 若是一次只能接收最多不超过8192的数据 ,那服务端返回的数据超过了这个数字怎么办呢?好比让服务器端打开一个5mb的文件并返回,客户端怎么才能完整的接受到呢?那就只能循环收取啦。 

 

在开始解决上面问题3以前,咱们要考虑,客户端要循环接收服务器端的大量数据返回直到一条命令的结果所有返回为止, 但问题是客户端知道服务器端返回的数据有多大么?答案是不知道,那既然不知道服务器的要返回多大的数据,那客户端怎么知道要循环接收多少次呢?答案是不知道,擦,那咋办? 总不能靠猜吧?呵呵。。。 固然不能,那只能让服务器在发送数据以前主动告诉客户端,要发送多少数据给客户端,而后再开始发送数据,yes, 机智如我,搞起。缓存

先简单测试接收数据量大小服务器

 

 1 import socket
 2 import os,subprocess
 3 
 4 
 5 server = socket.socket() #得到socket实例
 6 server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 7 
 8 server.bind(("localhost",9998)) #绑定ip port
 9 server.listen()  #开始监听
10 
11 while True: #第一层loop
12     print("等待客户端的链接...")
13     conn,addr = server.accept() #接受并创建与客户端的链接,程序在此处开始阻塞,只到有客户端链接进来...
14     print("新链接:",addr )
15     while True:
16 
17         data = conn.recv(1024)
18         if not data:
19             print("客户端断开了...")
20             break #这里断开就会再次回到第一次外层的loop
21         print("收到命令:",data)
22         #res = os.popen(data.decode()).read() #py3 里socket发送的只有bytes,os.popen又只能接受str,因此要decode一下
23         res = subprocess.Popen(data,shell=True,stdout=subprocess.PIPE).stdout.read() #跟上面那条命令的效果是同样的
24         if len(res) == 0:
25             res = "cmd exec success,has not output!"
26         conn.send(str(len(res)).endcode("utf-8")) #发送数据以前,先告诉客户端要发多少数据给它
27         conn.sendall(res.encode("utf-8")) #发送端也有最大数据量限制,因此这里用sendall,至关于重复循环调用conn.send,直至数据发送完毕
28 
29 server.close()

 

 

import socket

client = socket.socket()

client.connect(("localhost",9998))

while True:
    msg = input(">>:").strip()
    if len(msg) == 0:continue
    client.send( msg.encode("utf-8") )

    res_return_size  = client.recv(1024) #接收这条命令执行结果的大小
    print("getting cmd result , ", res_return_size)
    total_rece_size = int(res_return_size)
    print(total_rece_size)

    #print(data.decode()) #命令执行结果

client.close()
相关文章
相关标签/搜索