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'))
server 端

  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'))
client 端代码

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  相关方法以及参数介绍:                                              

 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()
server 端代码

  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()
client 端代码

  在进行类型转换的时候: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_sever

  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()
cmd_client

二、编码问题

  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袁浩
编码实例 

 

猜你喜欢

转载自www.cnblogs.com/jinzejun/p/9037684.html