1 网络通信要素
OSI模型定义不同计算机互联网的标准,设计和描述计算机网络通信的基本框架。
1)IP地址:用来表示网络上一台独立的主机;IP地址=网络地址+主机地址;特殊IP地址:127.0.0.1(本地回环地址,保留地址,点份十进制)。
2)端口号:要将数据发送到对方的指定的应用程序上,为了表示这些应用程序,所有这些网络应用程序都用数字进行标识,为了方便称呼这些数字,则将这些数字称为端口。
3)传送协议:通讯的规则,例如:TCP,UDP协议(好比两个人用统一中国语言进行交流)。
2 网络通讯步骤
确定对方IP地址->确定应用程序端口->确定通讯协议
网络通讯的过程其实就是一个(源端)不断的封装数据包(目的端)不断拆数据包的过程。
3 通信的方法
server下的方法
sk.accept()接收的是客户端的sk相关信息,返回信息类型为元组。
bind()
listen()
send()
sendall()
recv()
close(),关通道与关服务器是不同的。关通道不影响其它通道。
1 import socket
2
3 # family=AF_INET是指定使用何种的地址类型,ADDRESS FAMILY是地址族,INET:internetwork。
4 # type确定设置通信的协议类型,SOCK_SREAM。
5 sk = socket.socket()
6 print(sk)
7 # 绑定IP地址
8 address = ('127.0.0.1', 8000)
9 sk.bind(address)
10 sk.listen(3) # 确定连接的最大数量
11 print("waitting...")
12 # conn就是通道,所有的数据连接都是通过conn连接。
13 conn, addr = sk.accept() # 创建连接
14 inp = input("请输入")
15 conn.send(bytes(inp, 'utf-8')) # 传送的类型是bytes类型
服务端
client下的方法
listen()
recv()
send()
close()
1 import socket
2
3 # 不需要绑定,直接绑定
4 sk = socket.socket()
5 address = ('127.0.0.1', 8000)
6 sk.connect(address)
7
8 data = sk.recv(1024) # 一次最大接收多少
9 print(str(data, 'utf-8')) # 如果接受是汉字,需要进行编码
10
11 # 只关闭自己的通道,其它的对象没有关系
12 sk.close()
客户端
4 实际应用聊天
1 import socket
2
3 sk = socket.socket()
4 print(sk)
5 address = ('127.0.0.1', 8000)
6 sk.bind(address)
7 sk.listen(3) # 最大排队数,排队数量为3个。
8 print("waitting...")
9 # conn, addr = sk.accept() # 此处也可增加一个while循环。
10
11
12 while 1:
13 conn, addr = sk.accept()
14 print(addr)
15 while True:
16 try:
17 data = conn.recv(1024) # 此处异常关闭客户端会出现异常
18 except Exception as e:
19 print(e)
20 break # 跳出里层的循环
21 if not data:
22 break
23 inp = input("请输入")
24 conn.send(bytes(inp, 'utf-8')) # 传送的类型是bytes类型
25
26 conn.close()
server
1 import socket
2
3 # 不需要绑定,直接绑定
4 sk = socket.socket()
5 address = ('127.0.0.1', 8000)
6 sk.connect(address)
7
8 while True:
9 inp = input('>>>')
10 if inp == "exit":
11 break
12 sk.send(bytes(inp, 'utf-8')) # 不能发空
13
14 data = sk.recv(1024) # 一次最大接收多少
15 print(str(data, 'utf-8')) # 如果接受是汉字,需要进行编码
16 sk.close()
client
5 远程执行命令
编码:从明文到编码文本的转换过程叫做编码。
解码:从编码文本到明文的转换过程叫做解码。
Python2的string编码
在Python2中,有两种字符串类型:str类型和unicode类型;注意,这仅仅是两个名字,python定义的两个名字,关键是这两种数据类型在程序运行时存在内存地址的是什么?内置函数repr可以帮我们在这里显示存储内容。原来,str和unicode分别存的是字节数据和unicode数据。
Python3的string编码
Python3也有两种数据类型:str和bytes; str类型存unicode数据,bytse类型存bytes数据,与py2比只是换了一下名字而已
文件从磁盘到内存的编码
例如在文本编辑器word上编辑文字的时候,在保存数据之前通过unicode的形式存在内存中,当保存到磁盘上时通过某种编码方式编码成bytes字节串,例如utf-8等,
1 s = 'hello 袁浩' # uicode万国码,在哪个国家都是相同的
2 print(type(s)) # <class 'str'>
3
4 # 由str到bytes:编码
5 b1 = bytes(s, 'utf-8')
6 print("b1", b1) # b'hello \xe8\xa2\x81\xe6\xb5\xa9' UTF-8规则下的bytes类型
7 b2 = s.encode('utf-8') # encode()是编码,有看到的数字转化为utf-8的数字
8 print("b2", b2)
9 b3 = s.encode('gbk')
10 print("b3", b3)
11
12
13 # 由bytes到str:解码
14 s1 = str(b2, 'utf-8') # 解码的一种方式
15 print('s1', s1)
16 s2 = b2.decode('utf-8')
17 print('s2', s2)
18 s3 = b3.decode('gbk')
19 print('s3', s3)
20
21
22 # cmd_result = obj.stdout.read() # 数据类型为gbk,Windows下自动转成gbk
编码和解码的操作
1 import socket
2 import subprocess
3
4 sk = socket.socket()
5 print(sk)
6 address = ('127.0.0.1', 8000)
7 sk.bind(address)
8 sk.listen(3) # 最大排队数,排队数量为3个。
9 print("waitting...")
10
11 while 1:
12 conn, addr = sk.accept()
13 print(addr)
14 while True:
15 try:
16 data = conn.recv(1024) # 此处异常关闭客户端会出现异常
17 except Exception as e:
18 break # 跳出里层的循环
19 if not data:
20 break
21 print('-------', str(data, 'utf-8'))
22 obj = subprocess.Popen(str(data, 'utf-8'), shell=True, stdout=subprocess.PIPE) # PIPE是个类
23 cmd_result = obj.stdout.read()
24 result_len = bytes(str(len(cmd_result)), 'utf-8') # int和bytes不能直接转,需要有通过str来转
25 conn.sendall(result_len) # 粘包现象,连续send()
26 conn.recv(1024)
27 conn.sendall(cmd_result) # 传送的类型是bytes类型
28
29 sk.close()
cmd_server
1 import socket
2
3 # 不需要绑定,直接绑定
4 sk = socket.socket()
5 address = ('127.0.0.1', 8000)
6 sk.connect(address)
7
8 while True:
9 inp = input('>>>')
10 if inp == "exit":
11 break
12 sk.send(bytes(inp, 'utf-8')) # 不能发空
13 result_len = int(str(sk.recv(1024), 'utf-8'))
14 sk.sendall('ok') # 解决粘包现象
15 print(result_len)
16 data = bytes()
17 while len(data) != result_len:
18 recv = sk.recv(1024) # 一次最大接收多少
19 data += recv
20 print(str(data, 'gbk')) # 如果接受是汉字,需要进行编码
21
22 sk.close()
cmd_client
6 文件上传
1 import socket
2 import subprocess
3 import os
4
5 sk = socket.socket()
6 print(sk)
7 address = ('127.0.0.1', 8000)
8 sk.bind(address)
9 sk.listen(3) # 最大排队数,排队数量为3个。
10 print("waitting...")
11 BASE_DIR = os.path.dirname(os.path.abspath(__file__))
12
13 while True:
14 conn, addr = sk.accept()
15 while True:
16 data = conn.recv(1024)
17 cmd, filename, filesize = str(data, 'utf-8').split('|')
18 path = os.path.join(BASE_DIR, 'yuan', filename)
19 filesize = int(filesize)
20
21 f = open(path, 'ab')
22 has_receive = 0
23 while has_receive != filesize:
24 data = conn.recv(1024)
25 f.write(data)
26 has_receive += len(data)
27 f.close()
28 sk.close()
server
1 import socket
2 import os
3
4 sk = socket.socket()
5 print(sk)
6
7 addresss = ('127.0.0.1', 8000)
8 sk.connect(addresss)
9
10 BASE_DIR = os.path.dirname(os.path.abspath(__file__))
11
12 inp = input('>>>').strip() # post|产品目录1.xlsx
13
14 cmd, path = inp.split('|')
15 path = os.path.join(BASE_DIR, path) # 文件的绝对路径
16
17 filename = os.path.basename(path) # 取名字
18 filesize = os.stat(path).st_size
19
20 file_info = 'post|%s|%s' % (filename, filesize)
21 sk.sendall(bytes(file_info, 'utf-8'))
22
23 f = open(path, 'rb')
24 has_sent = 0
25 while has_sent != filesize:
26 data = f.read(1024)
27 sk.sendall(data)
28 has_sent += len(data) # int数据类型
29 f.close()
30 print('上传成功')
31
32 sk.close()
client
7 socketserver模块
1 import socketserver
2
3
4 class MyServer(socketserver.BaseRequestHandler): # 继承里面的类是固定的
5
6 def handle(self):
7 print('服务端启动...')
8 while True:
9 conn = self.request
10 print('来自服务端的地址:', self.client_address)
11 while True:
12 client_data = conn.recv(1024)
13 print("收到客户端信息:", str(client_data, 'utf-8'))
14 # print('服务端准备输入发送数据!')
15 server_response = input("服务端准输入:")
16 conn.sendall(bytes(server_response, 'utf-8')) # 原路返回
17 conn.close()
18
19
20 if __name__ == "__main__":
21 server = socketserver.ThreadingTCPServer(('127.0.0.1', 8091), MyServer)
22
23 server.serve_forever() # 启动
server
1 import socket
2
3 ip_port = ('127.0.0.1', 8091)
4 sk = socket.socket()
5 sk.connect(ip_port)
6 print('客户端启动:')
7
8 while True:
9 inp = input("客户端输入:")
10 if inp == 'exit':
11 break
12 sk.sendall(bytes(inp, 'utf-8'))
13 data = sk.recv(1024)
14 print('服务器返回:', str(data, 'utf-8'))
15
16 sk.close()
client