目录

一、反射

二、socket

三、socketserver


一、反射

python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。

 class Foo(object):

     def __init__(self):
self.name = 'wupeiqi' def func(self):
return 'func' obj = Foo() # #### 检查是否含有成员 ####
hasattr(obj, 'name')
hasattr(obj, 'func') # #### 获取成员 ####
getattr(obj, 'name')
getattr(obj, 'func') # #### 设置成员 ####
setattr(obj, 'age', 18)
setattr(obj, 'show', lambda num: num + 1) # #### 删除成员 ####
delattr(obj, 'name')
delattr(obj, 'func')

详细解析:

当我们要访问一个对象的成员时,应该是这样操作:

 class Foo(object):                                                 

     def __init__(self):
self.name = 'tom' def func(self):
return 'func' obj = Foo() # 访问字段
obj.name
# 执行方法
obj.func()

那么问题来了?
a、上述访问对象成员的 name 和 func 是什么? 
答:是变量名
b、obj.xxx 是什么意思? 
答:obj.xxx 表示去obj中或类中寻找变量名 xxx,并获取对应内存地址中的内容。
c、需求:请使用其他方式获取obj对象中的name变量指向内存中的值 “tom”
 class Foo(object):

     def __init__(self):
self.name = 'tom' # 不允许使用 obj.name
obj = Foo()

答:有两种方法,如下:

 class Foo(object):

     def __init__(self):
self.name = 'alex' def func(self):
return 'func' # 不允许使用 obj.name
obj = Foo() print obj.__dict__['name']

方法一

 class Foo(object):

     def __init__(self):
self.name = 'alex' def func(self):
return 'func' # 不允许使用 obj.name
obj = Foo() print getattr(obj, 'name')

方法二

d、比较三种访问方式

  • obj.name
  • obj.__dict__['name']
  • getattr(obj, 'name')

答:第一种和其他种比,...
      第二种和第三种比,...

结论:反射是通过字符串的形式操作对象相关的成员。一切事物都是对象!!!

 import sys

 class WebServer(object):
def __init__(self,host,port):
self.host = host
self.port = port def start(self):
print('start') def stop(self):
print("stop") def restart(self):
self.stop()
self.start() if __name__ == "__main__":
server = WebServer('localhost',333)
if hasattr(server,sys.argv[1]):
func = getattr(server,sys.argv[1])
func()

例子

类也是对象

 class Foo(object):

     staticField = "old boy"

     def __init__(self):
self.name = 'wupeiqi' def func(self):
return 'func' @staticmethod
def bar():
return 'bar' print getattr(Foo, 'staticField')
print getattr(Foo, 'func')
print getattr(Foo, 'bar')

模块也是对象

 #!/usr/bin/env python
# -*- coding:utf-8 -*- def dev():
return 'dev'

home.py

 #!/usr/bin/env python
# -*- coding:utf-8 -*- """
程序目录:
home.py
index.py 当前文件:
index.py
""" import home as obj #obj.dev() func = getattr(obj, 'dev')
func()

index.py


二、socket

socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求。

socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件用【打开】【读写】【关闭】模式来操作。socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)

socket和file的区别:

  • file模块是针对某个指定文件进行【打开】【读写】【关闭】
  • socket模块是针对 服务器端 和 客户端Socket 进行【打开】【读写】【关闭】

socket服务端与客户端交流示意图:


socket()模块函数

使用socket.socket()函数来创建套接字,语法如下:

socket(socket_family,socket_type,protocol=0)

如前所述,参数一:socket_family(地址簇)

socket.AF_UNIX    只能用于单一的UNIX系统进程间通信

socket.AF_INET     IPV4(默认)

socket.AF_INET6   IPV6

参数二:socket_type(类型)

socket.SOCK_STREAM 流式socket , for TCP (默认)
socket.SOCK_DGRAM 数据报式socket , for UDP

socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。

socket.SOCK_RDM 是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。

socket.SOCK_SEQPACKET 可靠的连续数据包服务

参数三:protocol(协议)

0 (默认)与特定的地址家族相关的协议,如果是 0 ,则系统就会根据地址格式和套接类别,自动选择一个合适的协议

创建一个TCP/IP的套接字,你要这样调用socket.socket():

tcpsocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

同样的,创建一个UDP/IP的套接字,你要这样:

udpsocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

套接字对象(内建)方法:

函数 描述
服务器套接字函数  
s.bind(address) 绑定地址(主机名,端口号对)到套接字
s.listen(backlog) 开始TCP监听
s.accept() 被动接受TCP客户端连接,(阻塞式)等待链接的到来
客户端套接字函数  
s.connect() 主动初始化TCP服务器连接
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
公共用途的套接字函数  
s.recv() 接收TCP数据
s.send() 发送TCP数据
s.sendall() 完整发送TCP数据(不停调用s.send())
s.recvfrom() 接收UDP数据
s.sendto() 发送UDP数据
s.getpeername() 链接到当前套接字的远端的地址(TCP连接)
s.getsockname() 当前套接字的地址
s.getsockopt() 返回指定套接字的参数
s.setsockopt() 设置指定套接字的参数
s.close() 关闭套接字
面向模块的套接字函数  
s.setblocking() 设置套接字的阻塞与非阻塞模式
s.settimeout() 设置阻塞套接字操作的超时时间
s.gettimeout() 得到阻塞套接字操作的超时时间
面向文件的套接字函数  
s.fileno() 套接字的文件描述
s.makefile() 创建一个与该套接字相关联的文件对象

例:(win环境)

server端

#!/usr/bin/env python
# -*- coding:utf-8 -*- import socket ip_port = ('127.0.0.1',9999) sk = socket.socket()
sk.bind(ip_port)
sk.listen(5) while True:
print('server waiting...')
conn,addr = sk.accept()
client_data = conn.recv(1024)
print(str(client_data,'utf8'))
conn.sendall(bytes('不要回答,不要回答,不要回答','utf8')) conn.close()

client端

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
ip_port = ('127.0.0.1',9999) sk = socket.socket()
sk.connect(ip_port) sk.sendall(bytes('请求占领地球','utf8')) server_reply = sk.recv(1024)
print(str(server_reply,'utf8')) sk.close()

连续交互通信实例:

server端:(win环境)

#!/usr/bin/env python
# -*- coding:utf-8 -*- import socket ip_port = ('127.0.0.1',9999) sk = socket.socket()
sk.bind(ip_port)
sk.listen(5) while True:
print('server waiting...')
conn,addr = sk.accept()
client_data = conn.recv(1024)
print(str(client_data,'utf8'))
conn.sendall(bytes('不要回答,不要回答,不要回答','utf8'))
while True:
try:
            client_data = conn.recv(1024)
print(str(client_data,'utf8'))
server_response = input('>>>:').strip() except Exception:
            print("client closed,break")
            break
        conn.send(bytes(server_response,'utf8'))
conn.close()

server端:(Linux环境)

#!/usr/bin/env python
# -*- coding:utf-8 -*- import socket ip_port = ('127.0.0.1',9999) sk = socket.socket()
sk.bind(ip_port)
sk.listen(5) while True:
print('server waiting...')
conn,addr = sk.accept()
client_data = conn.recv(1024)
print(str(client_data,'utf8'))
conn.sendall(bytes('不要回答,不要回答,不要回答','utf8'))
while True:
client_data = conn.recv(1024)
print(str(client_data,'utf8'))
        server_response = input('>>>:').strip()
if not client_data:break
conn.send(server_response) conn.close()

client端:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
ip_port = ('127.0.0.1',9999) sk = socket.socket()
sk.connect(ip_port) sk.sendall(bytes('请求占领地球','utf8'))
server_reply = sk.recv(1024)
print(str(server_reply,'utf8'))
while True:
user_input = input(">>>").strip()
sk.send(bytes(user_input,'utf8'))
server_reply = sk.recv(1024)
print(str(server_reply,'utf8')) sk.close()

模拟实现简单ssh功能:

server端:

#!/usr/bin/env python
# -*- coding:utf-8 -*- import socket
import subprocess
ip_port = ('127.0.0.1',9999) sk = socket.socket()
sk.bind(ip_port)
sk.listen(5) while True:
print('server waiting...')
conn,addr = sk.accept()
while True:
client_data = conn.recv(1024)
if not client_data:break
print("recv cmd:",str(client_data,'utf8'))
cmd = str(client_data,'utf8').strip()
cmd_call = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
cmd_result = cmd_call.stdout.read()
if len(cmd_result) == 0:
cmd_result = b"cmd execution has no output..."
ack_msg = bytes("CMD_RESULT_SIZE|%s"%len(cmd_result),"utf8")
conn.send(ack_msg)
client_ack = conn.recv(50)
if client_ack.decode() == "CLIENT_READY_TO_RECV":
conn.send(cmd_result) conn.close()

client端:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
ip_port = ('127.0.0.1',9999) sk = socket.socket()
sk.connect(ip_port)
while True:
user_input = input("cmd:").strip()
if len(user_input) == 0:continue
if user_input == "q":break
sk.send(bytes(user_input,'utf8'))
#ack_msg = b"CMD_RESULT_SIZE|%s",len(cmd_result)
server_ack_msg = sk.recv(100)
cmd_res_msg = str(server_ack_msg.decode()).split("|")
print("server response:",cmd_res_msg)
if cmd_res_msg[0] == "CMD_RESULT_SIZE":
cmd_res_size = int(cmd_res_msg[1])
sk.send(b"CLIENT_READY_TO_RECV")
res = ''
received_size = 0
while received_size < cmd_res_size:
data = sk.recv(500)
received_size += len(data)
res += str(data.decode())
else:
print(str(res))
print("----------recv doen----------")
sk.close()

三、sockeserver

SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进程” 专门负责处理当前客户端的所有请求。

例:

server端:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
def setup(self):
print("Building secure connection chanel...")
def handle(self):
print("New Conn:",self.client_address)
while True: data = self.request.recv(1024)
if not data:break
print("Client Says:",data.decode())
self.request.send(data)
def finish(self):
print("client conn is done...")
if __name__ == '__main__':
HOST, PORT = "localhost", 50007
# 把刚才写的类当作一个参数传给ThreadingTCPServer这个类,下面的代码就创建了一个多线程socket server
server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
# 启动这个server,这个server会一直运行,除非按ctrl-C停止
server.serve_forever()

client端:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
ip_port = ('127.0.0.1',50007) sk = socket.socket()
sk.connect(ip_port)
while True:
msg = input(">>:").strip()
sk.sendall(bytes(msg,'utf8'))
server_reply = sk.recv(1024)
print("Server Reply:",str(server_reply,'utf8'))
sk.close()

python学习day7的更多相关文章

  1. python学习Day7 数据类型的转换,字符编码演变历程

    一.数据类型的转换 1.1.1.字符转列表:lst1 = str.split(默认空格,也可依据指定字符分界),若无分界字符,就没法拆分,这时可以直接放进list转成列表 ----> s1 = ...

  2. Python学习-day7 类 部分socket

    这周还是继续关于类的学习,在面向对象的学习过程中又学习了网络编程,并且提交了编写FTP的作业. 复习一下类的相关概念和定义 类      属性           实例变量:内存中           ...

  3. python学习day7 数据类型及内置方法补充

    http://www.cnblogs.com/linhaifeng/articles/7133357.html#_label4 1.列表类型 用途:记录多个值(一般存放同属性的值) 定义方法 在[]内 ...

  4. python学习 day7 (3月8日)

    read()读出来了之后文件里就从之后开始  光标不知道在哪 编码的进阶: 背景: ASCII:英文字母,数字,特殊符号,------------>二进制的对应关系 str: 一个字符 ---- ...

  5. python学习-Day7

    目录 作业讲解 数据类型内置方法2 字符串(str) 列表(list) 类型转换 内置方法 索引取值 切片操作 步长 统计列表中元素的个数 成员运算 (in和not in) 列表添加元素的方式* 删除 ...

  6. python学习day7 深浅拷贝&文件操作

    4-4 day07 深浅拷贝&文件操作 .get()用法 返回指定键的值,如果值不在字典中返回默认值. info={'k1':'v1,'K2':'v2'}mes = info.get('k1' ...

  7. Python学习记录day7

    目录 Python学习记录day7 1. 面向过程 VS 面向对象 编程范式 2. 面向对象特性 3. 类的定义.构造函数和公有属性 4. 类的析构函数 5. 类的继承 6. 经典类vs新式类 7. ...

  8. python笔记 - day7

    python笔记 - day7 参考: http://www.cnblogs.com/wupeiqi/articles/5501365.html 面向对象,初级篇: http://www.cnblog ...

  9. 【目录】Python学习笔记

    目录:Python学习笔记 目标:坚持每天学习,每周一篇博文 1. Python学习笔记 - day1 - 概述及安装 2.Python学习笔记 - day2 - PyCharm的基本使用 3.Pyt ...

随机推荐

  1. php 中const和 define的区别

    在php中定义常量时,可用到const与define这两种方法,那他们到底有什么区别呢? 1.const用于类成员变量的定义,一经定义,不可修改.define不可用于类成员变量的定义,可用于全局常量. ...

  2. 七、适配器(Adapter)模式--结构模式(Structural Pattern)

    适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作. 类的 Adapter模式的结构: 类适配器类图: 由图中可以看出,Adaptee ...

  3. NOI十连测 第四测 T2

    思路:线段树套可持久化treap,可持久化treap我还是第一次听说.. 改题的时候没看数据范围..乱开数组T_T #include<algorithm> #include<cstd ...

  4. jQuery插件之jqzoom

    jqzoom是一款基于jQuery的图片方法插件. 使用方法:1.引入jQuery与jqzoom,jqzoom.css 2.准备两张一大一小大小相同的图片,小图片放在<img>标签的&qu ...

  5. linux source命令学习

    1. linux source命令的作用? 我们可能经常需要修改到诸如/etc/profile,~/.bash_profile等这样的配置文件, 一方面我们希望所作的修改在当前的环境中立即生效: 另一 ...

  6. grok 官方文档

    <pre name="code" class="html">grok: 解析任意文本并构造它: Grok 是当前最好的方式在logstash 解析蹩 ...

  7. Unity 集成联通SDK

    我相信Unity程序员都会遇到加入SDK的问题,我相信如果你不会android编程,我相信你的CPU当场计算过快而爆炸!  这里也写笔记希望能帮助大家 如果有讲错的地方,希望大家能回复并且提供答案!  ...

  8. Dice Notation(模拟)

    Dice Notation Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Submit  ...

  9. vue+webpack项目实战

    概述 -- 项目中会用到的插件 vue-router vue-resource 打包工具 webpack 依赖环境 node.js start 安装vue开发的模板 # 全局安装 vue-cli $ ...

  10. iOS 字体设置

    使用无衬线字体 body {     font-family: "Helvetica Neue", Helvetica, STHeiTi, sans-serif; }  iOS 4 ...