一、网络编程基础
1.概念
计算机网络:就是把分布在不同区域的计算机与专门的外部设备用通信线路连接成一个网络系统,从而使得计算机之间可以进行资源共享或者数据传递
网络编程:其实指的是同一个网络中不同设备之间的通信
2.计算机之间进行通信的必要条件
ip地址,端口号,网络协议
2.1ip地址
1》概念
ip地址,Internet Protocol Address,互联网协议地址,是联网设备和互联网之间的唯一标识,在同一个网段中,ip地址是唯一的
ip地址是数字型的,是一个32位整数,将其分成4组,每组8位,由二进制组成,每8位用圆点隔开,每个8位的整数转换为了0~255之间的十进制数
2》分类
形式分类:
ipv4:ip地址由4个字节组成,分为4段
ipv6:ip地址由6个字节组成,分为6段
功能分类:
A类:保留给政府机构,1.0.0.1~126.255.255.254
B类:分配给中型企业,128~191
C类:分配给任何有需要的个人,192~223
D类:用于组播,224~239
E类:用于实验,240~255
127.0.0.1,回送地址,一般指的是本机的ip,可以使用localhost代替,通常用于测试
ip地址可以唯一的确定网络上的一个通信实体,但是一个通信实体可以有多个通信程序可以同时提供网络服务,此时还需要端口
2.2端口
port
1》概念
数据的发送和接收都是需要端口进出计算机的,端口用于唯一的标记通信实体上用于网络通信的通信程序
注意:同一台电脑上的不同应用程序不能同时占用同一个端口,端口是数字型的,取值范围,0~65535
2》分类
a.公认端口:0~1023 注意:自定义功能的时候,一定不要使用公认端口
b.注册端口:1025~49151
c.私有/动态端口:1024~65535
3》常用端口
mysql:3306
tomcat:8080
qq:4000
网址默认端口:80
2.3网络协议
TCP/UDP:用来实现即时通信
HTTP:被动式协议,只有客户端主动发起请求,服务端才会做出响应
3.TCP
Transsimition Control Protocol,传输控制协议
特点:
a.安全的【确保接收方完全正确的接收发送方发送的消息】
b.面向连接的【三次握手,面向连接的协议,数据在发送之前必须首先要建立连接,需要耗时】
c.数据传输的效率较低
d.传输的数据大小没有限制
【面试题:简述TCP和UDP之间的区别】
使用经典的三次握手建立连接:
a.客户端向服务端发送一个请求
b.服务端收到请求之后,回客户端一个响应
c.客户端收到服务端的响应之后,回服务端一个确认信息
注意:使用TCP实现数据的传输需要有发送方和接收方,但是两个通信实体之间没有严格的客户端和服务端之分,在两个通信实体没有建立连接之前,必须有一个通信实体先做出主动姿态,主动发起连接请求
通信实体:Socket,套接字,可以用来发送和接收消息,用来表示打开了一个网络连接,打开一个套接字需要知道目标计算机的ip地址,端口号,执行协议类型
3.1socket的通信流程
大多数可靠的连接都是TCP,创建TCP时,主动发起连接被称为客户端,被动接收请求被称为服务端
见图
3.2tcp编程
代码演示:
客户端:
import socket #1.客户端创建socket clientSocket = socket.socket() #2.客户端打开socket,根据服务端的ip地址和端口号连接服务端socket #注意:端口号指的是服务端的端口号,客户端的数据从哪个端口号发出,由系统决定 #ip地址是要连接的目标计算机的ip地址 """ connect(address) address:(ip地址,端口号) """ ip_port = ("10.20.152.55",8888) clientSocket.connect(ip_port) #3.客户端向服务端发送消息【客户端向socket写入信息】 """ 注意:需要将字符串数据类型转换为字节类型 转换方式:encode() bytes() send(),表示一次性将消息发送出去 sendall():内部递归调用send,将所有的内容发送出去 """ #bytes(字符串,encoding="xx") clientSocket.sendall(bytes("你好啊",encoding="utf-8")) #4.关闭socket clientSocket.close()
服务端
#服务端流程描述 import socket #1.创建socket serverSocket = socket.socket() #2.服务端为socket绑定ip地址和端口号,默认协议为tcp #注意:端口号指的是服务端的端口号,ip地址可以省略 """ bind(address) address:ip地址,端口号,以元组传参,一般写法为bind((ip,port)) """ ip_port = ("",8888) serverSocket.bind(ip_port) #3.服务端监听,随时准备接受客户端发来的请求 #注意:只是一个监听的状态,此时的socket并没有被打开 """ listen(backlog) backlog:在拒绝连接之前,可以挂起的最大连接数量 backlog等于5,表示内核已经到了连接请求,但是服务器还没有调用accept进行连接处理,这个值不能无限大, """ serverSocket.listen(5) print("server waiting......") #4.服务端socket接受到客户端socket的请求,被动打开socket,开始接收客户端请求 #会出现阻塞,直到返回客户端的连接信息 """ 客户端socket对象,address = accept() """ conn,addr = serverSocket.accept() print("连接成功。。。。") #5.服务端读取消息 """ recv(size) 接收套接字的数据,数据以字节返回,size表示最多能够接收到的数据的大小, """ #注意:客户端发送的数据保存在客户端的socket中,所以,服务端要接收到消息,需要从客户端的socket中读取出来 client_data = conn.recv(1024) result = str(client_data,"utf-8") print(addr,result) #6.关闭socket serverSocket.close()
循环发送
客户端:
import socket client = socket.socket() client.connect(("10.20.152.55",9999)) while True: data = input("请输入要发送给服务端的消息:") client.send(data.encode("utf-8")) #接收服务端回复的消息 info = client.recv(1024) info = info.decode("utf-8") print("服务端回复给客户端的消息:",info) if data == "88" or info == "88": break
服务端
import socket server = socket.socket() server.bind(("",9999)) server.listen(5) print("waiting.....") clientSocket,address = server.accept() print("%s %s连接成功" % (str(clientSocket),address)) while True: data = clientSocket.recv(1024) print("客户端对服务端说:",data.decode("utf-8")) sendData = input("请输入回复给=客户端的消息:") clientSocket.send(sendData.encode("utf-8")) if data == "88" or sendData == "88": break
总结:
a.对于客户端,要主动连接服务端的ip地址和端口号,对于服务端而言,只需要绑定端口
b.每连接进来一个客户端,按照理论来说,都需要开辟一条新的线程或者进程处理
c.同一个端口,被一个socket绑定之后,就不能再次绑定其他的socket
d.tcp连接创建的是双向通道,双方都可以给对方发消息,同时,也可以接受对方发来的消息,至于谁先发,谁后发,由具体的需求来决定
3.3udp编程
User Datagram Protocol,用户数据包【报】协议,是面向事务的不可靠的传输协议
特点:
a.不安全的【发送方发送的数据不一定到达对方,发送发发出去的数据,接收方不一定完整的接收出来】
b.无连接的【将数据打包到数据包中】
c.效率高
d.传输的数据的大小有限制,每个被传输的数据包的大小在64k以内
代码演示:
服务端:
#服务端 import socket server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #注意:端口号指的是服务端的端口号 server.bind(("",6666)) #服务端接收数据 data,addr = server.recvfrom(1024) print("客户端%s说:%s" % (addr,data.decode("utf-8")))
客户端:
#客户端 import socket client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #发送数据 #参数:内容 address data = "hello" client.sendto(data.encode("utf-8"),("10.20.152.55",6666))
二、反射
1.概念
通过字符串的形式获取对象或者模块,操作【查找,获取,删除,添加】对象或者模块中的成员
是一种基于字符串的事件驱动
2.使用
案例一:
class Person(object): def __init__(self,name,age): self.name = name self.age = age self.__num = 37 def show(self): print("showing") @classmethod def func1(cls): print("func1") @staticmethod def func2(): print("func2") p = Person("张三",18) #获取name的值 #print(p.name) #如果有一个字符串"name",获取name的值 """ name "name" age "age" """ #1.getattr(object,name,default) attribute,获取某个对象的属性对应的值,如果指定的属性不存在,则获取的是default的值 """ object:指定的对象 name:指定对象的指定属性名,是一个字符串 default:默认值 """ #1.1获取成员变量 value1 = getattr(p,"name","tom") print(value1) value2 = getattr(p,"age",19) print(value2) value3 = getattr(p,"name1","bob") print(value3) #私有化属性:_Person__num value4 = getattr(p,"_Person__num",10) print(value4) #1.2获取成员函数 #通过函数名的字段获取出来,可以直接调用 #p.show() value5 = getattr(p,"show") print(value5) value5() #1.3获取静态函数和类函数 #类函数和静态函数属于类,同时也属于对象 #f1 = getattr(p,"func1") f1 = getattr(Person,"func1") print(f1) f1() #f2 = getattr(p,"func2") f2 = getattr(Person,"func2") print(f2) f2() #2.setattr(object,name,value):设置,为某个指定对象的某个属性重新赋值 p1 = Person("lisi",37) setattr(p1,"name","大黄") #p1.name = "大黄" result = getattr(p1,"name") #print(p1.name) print(result) #3.hasattr(object,name),isxxxx,hasxxx,判断 #在使用之前可用来进行判断,为了保证代码的严谨性 print(hasattr(p1,"name")) print(hasattr(p1,"score")) #4.delattr(object,name) 删除指定对象中的指定属性 delattr(p1,"name") #del p1.name #print(getattr(p1,"name")) #print(p1.name) print(getattr(p,"name"))
案例二:
num = 27 def show(): print("a~~~~show") class A(object): def __init__(self,name): self.name = name
import reflect02.a #注意:万物皆对象,一个模块也是一个对象 print(getattr(reflect02.a,"num")) r0 = getattr(reflect02.a,"show") print(r0) r0() r1 = getattr(reflect02.a,"A") print(r1) r2 = r1("abc") print(r2)
案例三:
def news(): return "新闻" def games(): return "游戏" def pic(): return "图片" def video(): return "视频" def music(): return "音乐" def caijing(): return "财经"
#from reflect03.module import * import reflect03.module value = input("请输入对应的模块:") """ if value == "news": print(news()) elif value == "games": print(games()) elif value == "pic": print(pic()) elif value == "video": print(video()) elif value == "music": print(music()) elif value == "caijing": print(caijing()) else: print("没有指定的模块") """ #使用反射实现上面相同的需求 #可以先判断有没有指定的模块 result = hasattr(reflect03.module,value) if result: #说明模块存在的 #从模块获取指定的成员函数 f = getattr(reflect03.module,value) print(f()) else: print("没有指定的模块")
三、Python2.x和Python3.x的区别
1.性能
py3.x起始比py2.x效率低,但是py3.x有极大的优化空间,效率正在追赶
2.编码
py3.x源码文件默认使用utf-8编码,使得变量名更为广阔【可以使用中文作为变量名】
3.语法
1>去除了<>,改用!=
2>加入as和with关键字,还有True,False,None
3>整型触发返回浮点数,整除请使用//【5/3结果为取整的1,5.0/3结果为浮点型的1.66666,而5.0//3结果则为取整1.0】
4>加入nonlocal语句【使用嵌套变量】
5>去除print语句,加入print()函数
6>去除raw_input语句,加入input()函数
7>新的super(),可以不再给super()传参数
8>改变了顺序操作符的行为,例如x<y,当x和y类型不匹配时抛出TypeError而不是返回随即的布尔值
9>新式的8进制字面量:py2.x使用0表示8进制,py3.x使用0o表示8进制
4.字符串和字节串
py2.x以8-bit字符串存储,py3.x以16-bit Unicode字符串存储
现在字符串只有str一种类型
5.数据类型
py3.x去除了long类型,现在只有一种整型-int,但是它的行为就像2.x的long
py3.x新增了bytes类型,对应于2.x版本的八位串,str对象和bytes对象可以使用encode()和decode()方法进行相互转化
6.面向对象
py3.x引入了抽象基类
7.异常
异常都从BaseException继承,并删除了StardardError
py2.x:
try: except Exception,e:
py3.x:
try: except Exception as e:
8.其他
xrange()改名为range(),要想使用range()获得一个list,必须显式调用
file类被废弃
py2.x:打开文件需要两步,file(path) open(path) py3.x:打开文件只需要一步,open(path)