Python 3学习 ——网络编程
Posted jinzejun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 3学习 ——网络编程相关的知识,希望对你有一定的参考价值。
Python 学习——面向对象
写此博客 是为了激励自己,并且将自己的心得以及遇到的问题与人分享
一、网络编程
SOCK_STRAM :TCP SOCK_Dgram :UDP 两个参数决定了不同的连接方式,主要使用TCP连接。
family = AF_INET :服务器之间的通信 family = AF_UNIX :Unix 不同进程的通信。
send 或者 sendall 方法传送的类型一定要是 bytes 类型。
(相互通信)小应用:server 端 和 client 端进行通信。
server 端代码:
1 #author:"LFD" 2 #date: 2018/5/14 3 4 import socket 5 6 sk = socket.socket() #什么都不加就可以了,参数已经默认写好了 7 print(sk) #<socket.socket fd=428, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0> 8 9 address = (‘127.0.0.1‘,8000) #回环地址,代表了默认的IP地址就是当前这台电脑的IP地址。 8000是端口号。 10 11 sk.bind(address) # 绑定了IP地址和端口 12 13 sk.listen(3) # 决定着serve端到底可以容纳多少个排队人数。 14 print(‘我在等待连接‘) 15 con,addr = sk.accept() 16 print(con) #(<socket.socket fd=504, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, 17 #proto=0, laddr=(‘127.0.0.1‘, 8000), raddr=(‘127.0.0.1‘, 7311)>, (‘127.0.0.1‘, 7311)) 18 19 # inp = input(‘请输入要发送的内容:‘) 20 # con.send(bytes(inp,‘utf8‘)) 21 22 data = con.recv(1024) # 注意! 为什么用con 23 print(str(data,‘utf8‘))
client 端代码:
1 #author:"LFD" 2 #date: 2018/5/14 3 4 import socket 5 6 sk = socket.socket() # 同样建立一个socket连接。 7 print(sk) #<socket.socket fd=428, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0> 8 9 10 address = (‘127.0.0.1‘,8000) # 代指本机IP地址,8000是端口号 11 12 sk.connect(address) 13 14 # data = sk.recv(1024) 15 # print(str(data,‘utf8‘)) 16 inp = input(‘请输入您要发送的内容:‘) 17 sk.send(bytes(inp,‘utf8‘))
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
相关方法以及参数介绍:
1 sk.bind(address) 2 3 #s.bind(address) 将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址。 4 5 sk.listen(backlog) 6 7 #开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。 8 9 #backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的连接个数最大为5 10 #这个值不能无限大,因为要在内核中维护连接队列 11 12 sk.setblocking(bool) 13 14 #是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。 15 16 sk.accept() 17 18 #接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。 19 20 #接收TCP 客户的连接(阻塞式)等待连接的到来 21 22 sk.connect(address) 23 24 #连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。 25 26 sk.connect_ex(address) 27 28 #同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:10061 29 30 sk.close() 31 32 #关闭套接字 33 34 sk.recv(bufsize[,flag]) 35 36 #接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略。 37 38 sk.recvfrom(bufsize[.flag]) 39 40 #与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。 41 42 sk.send(string[,flag]) 43 44 #将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。 45 46 sk.sendall(string[,flag]) 47 48 #将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。 49 50 #内部通过递归调用send,将所有内容发送出去。 51 52 sk.sendto(string[,flag],address) 53 54 #将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。 55 56 sk.settimeout(timeout) 57 58 #设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如 client 连接最多等待5s ) 59 60 sk.getpeername() 61 62 #返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。 63 64 sk.getsockname() 65 66 #返回套接字自己的地址。通常是一个元组(ipaddr,port) 67 68 sk.fileno() 69 70 #套接字的文件描述符
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
(升级版)小应用:server 端 和 client 端进行通信。client 端和server 端都可以主动进行关闭,并且当client 端关闭后,server 端可以等待下次连接。
server 端代码
1 #author:"LFD" 2 #date: 2018/5/14 3 4 import socket 5 6 sk = socket.socket() #什么都不加就可以了,参数已经默认写好了 7 #print(sk) #<socket.socket fd=428, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0> 8 9 address = (‘127.0.0.1‘,8000) #回环地址,代表了默认的IP地址就是当前这台电脑的IP地址。 8000是端口号。 10 11 sk.bind(address) # 绑定了IP地址和端口 12 13 sk.listen(3) # 决定着serve端到底可以容纳多少个排队人数。 14 print(‘waiting...‘) 15 16 #print(con) #(<socket.socket fd=504, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, 17 #proto=0, laddr=(‘127.0.0.1‘, 8000), raddr=(‘127.0.0.1‘, 7311)>, (‘127.0.0.1‘, 7311)) 18 19 while 1: 20 con, addr = sk.accept() 21 print(addr) 22 while 1: 23 data = con.recv(1024) # 注意! 为什么用con 24 print(‘....‘,str(data,‘utf8‘)) 25 if not data:break 26 # con.close() 27 # con,addr = sk.accept() 28 # print(addr) 29 # continue 30 inp = input(‘请输入要发送的内容:‘) 31 if inp == ‘q‘: 32 break 33 con.send(bytes(inp, ‘utf8‘)) 34 35 con.close()
client 端代码
1 #author:"LFD" 2 #date: 2018/5/14 3 4 import socket 5 6 sk = socket.socket() # 同样建立一个socket连接。 7 #print(sk) #<socket.socket fd=428, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0> 8 9 10 address = (‘127.0.0.1‘,8000) # 代指本机IP地址,8000是端口号 11 12 sk.connect(address) 13 14 15 while 1: 16 inp = input(‘请输入您要发送的内容:‘) 17 18 if inp == ‘q‘: 19 break 20 sk.send(bytes(inp, ‘utf8‘)) 21 data = sk.recv(1024) 22 print(str(data,‘utf8‘)) 23 24 sk.close()
在进行类型转换的时候:bytes 类型 如果想转换成 int 类型,要经过 str 类型的过度,不可以直接强转成 int 类型,这样是转不成功的。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
(远程执行命令)小应用:远程执行命令。 client 端 向 server 端发送一个 shell 命令,server 端执行并返回结果。 重点在对文件字节未知的情况下,进行多次发送。 注意粘包现象——数据。
cmd_server 端代码
1 #author:"LFD" 2 #date: 2018/5/14 3 4 import socket 5 import subprocess # 执行shell命令 6 7 sk = socket.socket() #什么都不加就可以了,参数已经默认写好了 8 9 address = (‘127.0.0.1‘,8000) #回环地址,代表了默认的IP地址就是当前这台电脑的IP地址。 8000是端口号。 10 11 sk.bind(address) # 绑定了IP地址和端口 12 13 sk.listen(3) # 决定着serve端到底可以容纳多少个排队人数。 14 print(‘waiting...‘) 15 16 while 1: 17 con, addr = sk.accept() 18 print(addr) 19 while 1: 20 data = con.recv(1024) # 注意! 为什么用con 21 if not data:break 22 print(‘....‘,str(data,‘utf8‘)) 23 24 object = subprocess.Popen(str(data,‘utf8‘),shell=True,stdout=subprocess.PIPE) 25 26 cmd_result = object.stdout.read() 27 28 result_len = bytes(str(len(cmd_result)),‘utf8‘) 29 30 con.send(result_len)#发送完毕后可能会再等待一下,如果将后一个包的数据一起发送了,就产生了粘包现象。 31 32 con.recv(1024) #在两个发送之间添加一个接收阻塞。来解决粘包现象。 33 34 con.send(cmd_result) 35 36 37 con.close()
cmd_client 端代码
1 #author:"LFD" 2 #date: 2018/5/14 3 4 import socket 5 6 sk = socket.socket() # 同样建立一个socket连接。 7 8 address = (‘127.0.0.1‘,8000) # 代指本机IP地址,8000是端口号 9 10 sk.connect(address) 11 12 while 1: 13 inp = input(‘请输入您要发送的内容:‘) 14 15 if inp == ‘q‘: 16 break 17 sk.send(bytes(inp, ‘utf8‘)) 18 19 result_len = int(str(sk.recv(100),‘utf8‘)) 20 print(result_len) 21 22 sk.send(bytes(‘ok‘,‘utf8‘)) #做一个隔断,对粘包现象进行处理。 23 24 data = bytes() 25 while len(data) != result_len: 26 27 recv = sk.recv(1024) 28 data += recv 29 30 print(str(data,‘gbk‘)) 31 32 sk.close()
二、编码问题
Python3 中只有两种数据类型。str 、bytes。
str :unicode 数据类型是str,储存的是 unicode 的编码。
bytes:十六进制 有utf8 、gbk 编码的bytes 类型。拦住
由str ---> bytes 叫做编码;
1 #author:"LFD" 2 #date: 2018/5/2 3 4 # str -------> bytes 5 6 s = ‘hello袁浩‘ 7 8 b = bytes(s,‘utf8‘) 9 print(b) #b‘hello\xe8\xa2\x81\xe6\xb5\xa9‘ utf8 规则下的bytes 类型 10 11 b2 = s.encode(‘utf8‘) 12 print(b2) #b‘hello\xe8\xa2\x81\xe6\xb5\xa9‘ 编码方法 13 14 b3 = s.encode(‘gbk‘) 15 print(‘gbk 编码下的Bytes数据‘,b3) #gbk 编码下的Bytes数据 b‘hello\xd4\xac\xba\xc6‘ 16 17 18 19 # bytes -------> str 20 21 s = str(b2,‘gbk‘) 22 print(s) # hello琚佹旦 乱码 23 24 #解码方式1: 25 s2 = str(b2,‘utf8‘) 26 print(s2) # hello袁浩 str 类型 27 28 #解码方式2: 29 s3 = b2.decode(‘utf8‘) 30 print(s3) # hello袁浩 31 32 #解码方式3: 33 s4 = b3.decode(‘gbk‘) 34 print(s4) # hello袁浩
以上是关于Python 3学习 ——网络编程的主要内容,如果未能解决你的问题,请参考以下文章