目录

一、反射

二、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. Super Jumping! Jumping! Jumping!(hdu 1087 LIS变形)

    Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 ...

  2. hdu just a hook(线段树,区间修改)

    Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  3. JS设置获取cookies

    结合JavaScript权威指南,加上项目开发时在网上搜集的资料,整理了两种设置和获取cookie的方法. <script> //设置cookie  方法一function setCook ...

  4. org.quartz.impl.jdbcjobstore.LockException

    说明:在使用Tomcat6.0.32+Spring3.05+Quartz1.8.6+Mysql5.5.9 此项目在我本机上没有问题,当我把mysql 脚本导入到服务器上,将数据源配置修改为服务器对应的 ...

  5. 分布式文件系统MooseFS安装步骤

    1.    安装 1.1 准备安装环境 首先选择一台比较好的服务器做master,如果可以在选择一台做为master的备份服务器最好.然后其他的服务器当chunkserver. 为了方便说明问题,我这 ...

  6. bzoj1633 [Usaco2007 Feb]The Cow Lexicon 牛的词典

    Description 没有几个人知道,奶牛有她们自己的字典,里面的有W (1 ≤ W ≤ 600)个词,每个词的长度不超过25,且由小写字母组成.她们在交流时,由于各种原因,用词总是不那么准确.比如 ...

  7. Clone Graph 解答

    Question Clone an undirected graph. Each node in the graph contains a label and a list of its neighb ...

  8. apache FtpServer整合spring逻辑处理

    上面我们的部署工作完成了,那么文件上传下载后,ftpserver会自动相应我们的上传下载操作,也就是说ftpServer服务器会得到触发,那么我们如果要得到文件的一些信息,比如说文件的路径.大小.类型 ...

  9. textField 判断输入长度限制

    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementS ...

  10. ThreadPool(线程池) in .Net

    本文来自:http://rickie.cnblogs.com/archive/2004/11/23/67275.html 在多线程的程序中,经常会出现两种情况.一种情况下,应用程序中的线程把大部分的时 ...