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

网络通信   socket

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

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

  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()
时间: 2024-08-26 02:22:36

Python学习记录之----网络通信(二)的相关文章

Python学习记录——Ubuntu(二)用户和用户组

1.etc文件作用: (1) /etc/passwd 用户账户信息. (2)/etc/shadow 安全用户账户信息. (3)/etc/group 组账户信息. (4)/etc/gshadow 安全组账户信息. (5)/etc/default/useradd 账户创建的默认值. (6)/etc/skel/ 包含默认文件的目录. (7)/etc/login.defs Shadow 密码套件配置. 2.创建用户流程: (1)sudo useradd -m(创建用户主文件夹)-s(设置用户登陆所使用的

Python学习记录day6

Python学习记录day6 学习 python Python学习记录day6 1.反射 2.常用模块 2.1 sys 2.2 os 2.3 hashlib 2.3 re 1.反射 反射:利用字符串的形式去对象(默认)中操作(寻找)成员 cat commons.py #!/usr/bin/env python#_*_coding:utf-8_*_''' * Created on 2016/12/3 21:54. * @author: Chinge_Yang.''' def login(): pr

Python学习记录day3

Python学习记录 day3 今天是银角大王武sir讲课.先回顾了上节课所学,然后讲到了面向对象思想. set set是一个无序且不重复,可嵌套的元素集合 class set(object):     """     set() -> new empty set object     set(iterable) -> new set object     Build an unordered collection of unique elements.     

Python学习记录day1

Python学习记录博客是本人记录学习python3过程中的一些记录和过程,日后也可以帮助自己温习. python优点: 1.Python入门简单,功能强大,适用性强: 2.开发效率高,第三方库强大且多: 3.Python无需考虑底层细节: 4.可移植性,跨平台: 5.可扩展性: 6.可嵌入性,Pthon可嵌入到C/C++程序中: python缺点: 1.速度慢,Python比C慢很多,比java也慢一点: 2.代码不能加密,源码是明文: 3.线程不能利用多 CPU 问题: python版本2和

Python学习入门笔记(二):Python运算符

1.算术运算符 "+"加法:3+2=5 "-"减法:3-2=1 "*"乘法:3*2=6 "/"实数除法:3/2=1,3.0/2=1.5 "//"整数除法:5.6//2=2.0 "%"求余数:17%6=5 "**"求幂运算:2**3=8 2.赋值运算符 "="等于:x=3 "+="加等于:x+=2 "-="减等

python学习记录第五篇--遍历目录

#coding=utf-8'''@author: 简单遍历目录删除文件的小程序'''import os#查找文件操作def findFile(path): fileList=[] for rootPath,subRoot,fileName in os.walk(path): for sub in fileName: if os.path.isfile(os.path.join(rootPath,sub)): k=os.path.splitext(sub)[1].lower() if k in (

python学习记录第四篇--数据库

只要用到MySQLdb,使用时请先安装MySQLdb,百度上可以下载! #coding=utf-8'''@author: 使用python操作MySQL数据库'''import MySQLdb#import MySQLdb.cursorsconn=MySQLdb.connect(user='root',passwd='root') #connect共三个值,user,passwd,host,无密码且连接本地数据库时,可以都为空.cur=conn.cursor() #创建游标,使用游标进行数据库操

Python学习记录day5

title: Python学习记录day5 tags: python author: Chinge Yang date: 2016-11-26 1.多层装饰器 多层装饰器的原理是装饰器装饰函数后其实也是一个函数这样又可以被装饰器装饰. 编译是从下至上进行的执行时是从上至下进行. #!/usr/bin/env python # _*_coding:utf-8_*_ ''' * Created on 2016/11/29 20:38. * @author: Chinge_Yang. ''' USER

Python学习记录-socket编程

Python学习记录-socket编程 学习 python socket Python学习记录-socket编程 1. OSI七层模型详解 2. Python socket 3. socket()函数 4. TCP socket通信流程 5. Python Internet 模块 1. OSI七层模型详解 以上图见:http://blog.csdn.net/yaopeng_2005/article/details/7064869 其它详情可参考:socket网络基础 2. Python sock