数据的流向:Client-》客户端OS-》PC机-》网络设备-》服务器-》服务器OS-》Server

1)生活中通信举例:
2)计算机与计算机之间通信举例;
3)互联网协议-OSI七层;
1)、就是底层的物理链接介质+互联网协议;
2)、互联网协议就是计算机界的“英语”;
1)、物理层-L1;
功能:发送电信号0101110001;
2)、数据链路层-L2;
形成了统一的标准-Ethernet(以太网协议);
计算机通信基本靠吼;
3)、网络层-L3;
引出IP地址的概念;
4)、传输层-L4
TCP、UDP协议;
引出端口号的概念;1~65535;
IP+Port可以表示全世界范围内唯一一个软件;
一般来说,服务端会绑定IP和端口;而客户端不需要;
HTTP、FTP;




1)、接电话方:
1.首先你得有个电话 2.你的电话要有号码 3.你的电话必须连上电话线 4.开始在家等电话 5.电话铃响了,接起电话,听到对方的声音
2)、打电话方:
1.首先你得有个电话 2.输入你想拨打的电话 3.等待对方接听 4.say “hi 约么,我有七天酒店的打折卡噢~” 5.等待回应——》响应回应——》等待回应。。。。
1)、接电话方(socket服务器端):
1.首先你得有个电话\(生成socket对象\) 2.你的电话要有号码\(绑定本机ip+port\) 3.你的电话必须连上电话线\(连网\) 4.开始在家等电话\(开始监听电话listen\) 5.电话铃响了,接起电话,听到对方的声音\(接受新连接\)
2)、打电话方(socket客户端)
1.首先你得有个电话\(生成socket对象\) 2.输入你想拨打的电话\(connect 远程主机ip+port\) 3.等待对方接听 4.say “hi 约么,我有七天酒店的打折卡噢~”\(send\(\) 发消息。。。\) 5.等待回应——》响应回应——》等待回应。。。。




1)server.py;
import socket #1、买手机; phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #2、绑定手机卡; phone.bind((‘127.0.0.1‘,18081))#0~65535,其中0~1024,系统使用 #3、开机; phone.listen(5) #4、等电话来连接; print(‘starting....‘) # cxz = phone.accept() # print(cxz) conn,client_addr = phone.accept() #5、收、发消息; data = conn.recv(1024)#1、单位bytes;2、1024代表最大接受1024个bytes; print(‘客户端数据‘,data) conn.send(data.upper()) #6、挂电话; conn.close() #7、关机; phone.close()
2) client.py
import socket #1、买手机; phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #print(phone)#<socket.socket fd=428, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0> #2、拨号; phone.connect((‘127.0.0.1‘,18081))#ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。 #3、发、收消息; phone.send(‘hello‘.encode(‘utf-8‘)) data = phone.recv(1024) print(data) #4、关机; phone.close()
1)server.py
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind((‘127.0.0.1‘,18080))#0~65535,其中0~1024,系统使用;
phone.listen(5)
print(‘starting....‘)
conn,client_addr = phone.accept()
print(client_addr)
while True:
data = conn.recv(1024)#1、单位bytes;2、1024代表最大接受1024个bytes;
print(‘客户端数据‘,data)
conn.send(data.upper())
conn.close()
phone.close()
2)client.py
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect((‘127.0.0.1‘,18080))#ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。
while True:
msg = input(‘>>>:‘).strip()
phone.send(msg.encode(‘utf-8‘))
data = phone.recv(1024)
print(data)
phone.close()
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind((‘127.0.0.1‘,18080))#0~65535,其中0~1024,系统使用;
phone.listen(5)
print(‘starting....‘)
conn,client_addr = phone.accept()
print(client_addr)
while True:
try:
data = conn.recv(1024)#1、单位bytes;2、1024代表最大接受1024个bytes;
if not data:break#仅适用于Linux操作系统;
print(‘客户端数据‘,data)
conn.send(data.upper())
except ConnectionResetError:#适用于Windows操作系统;
break
conn.close()
phone.close()
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect((‘127.0.0.1‘,18080))#ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。
while True:
msg = input(‘>>>:‘).strip()
if not msg:continue
phone.send(msg.encode(‘utf-8‘))
data = phone.recv(1024)
print(data.decode(‘utf-8‘))
phone.close()
1)server.py
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind((‘127.0.0.1‘,18080))#0~65535,其中0~1024,系统使用;
phone.listen(5)
print(‘starting....‘)
while True:#链接循环;
conn,client_addr = phone.accept()
print(client_addr)
while True:#进入通信循环;
try:
data = conn.recv(1024)#1、单位bytes;2、1024代表最大接受1024个bytes;
if not data:break#仅适用于Linux操作系统;
print(‘客户端数据‘,data)
conn.send(data.upper())
except ConnectionResetError:#适用于Windows操作系统;
break
conn.close()
phone.close()
2)client1.py
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect((‘127.0.0.1‘,18080))#ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。
while True:
msg = input(‘>>>:‘).strip()
if not msg:continue
phone.send(msg.encode(‘utf-8‘))
data = phone.recv(1024)
print(data.decode(‘utf-8‘))
phone.close()
3)client2.py
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect((‘127.0.0.1‘,18080))#ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。
while True:
msg = input(‘>>>:‘).strip()
if not msg:continue
phone.send(msg.encode(‘utf-8‘))
data = phone.recv(1024)
print(data.decode(‘utf-8‘))
phone.close()


import socket
import os
import subprocess
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind((‘127.0.0.1‘,18080))#0~65535,其中0~1024,系统使用;
phone.listen(5)
print(‘starting....‘)
while True:#链接循环;
conn,client_addr = phone.accept()
print(client_addr)
while True:#进入通信循环;
try:
#1、收命令;
cmd = conn.recv(1024)#1、单位bytes;2、1024代表最大接受1024个bytes;
if not cmd:break#仅适用于Linux操作系统;
print(‘客户端数据‘,cmd)
#2、执行命令,拿到结果;
obj = subprocess.Popen(cmd.decode(‘utf-8‘), shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
# obj = subprocess.Popen(‘xxxxxipconfig‘,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
stdout = obj.stdout.read() # stdout1--->: b‘\r\nWindows IP \xc5\xe4\xd6\xc3\r\n\r\n\r\n\xd2\xd4\xcc\xab\xcd\xf8\xca\xca\xc5\xe4\xc6\xf7 \xd2\xd4\xcc\xab\xcd\xf8 2:\r\n\r\n \xc1\xac\xbd\xd3\xcc\xd8\xb6\xa8\xb5\xc4 DNS \xba\xf3\xd7\xba . . . . . . . : \r\n \xb1\xbe\xb5\xd8\xc1\xb4\xbd\xd3 IPv6 \xb5\xd8\xd6\xb7. . . . . . . . : fe80::fdc4:7f23:1928:6026%11\r\n IPv4 \xb5\xd8\xd6\xb7 . . . . . . . . . . . . : 192.168.1.5\r\n \xd7\xd3\xcd\xf8\xd1\xda\xc2\xeb . . . . . . . . . . . . : 255.255.255.0\r\n \xc4\xac\xc8\xcf\xcd\xf8\xb9\xd8. . . . . . . . . . . . . : fe80::1%11\r\n 192.168.1.1\r\n\r\n\xd2\xd4\xcc\xab\xcd\xf8\xca\xca\xc5\xe4\xc6\xf7 \xd2\xd4\xcc\xab\xcd\xf8 3:\r\n\r\n \xc3\xbd\xcc\xe5\xd7\xb4\xcc\xac . . . . . . . . . . . . : \xc3\xbd\xcc\xe5\xd2\xd1\xb6\xcf\xbf\xaa\xc1\xac\xbd\xd3\r\n \xc1\xac\xbd\xd3\xcc\xd8\xb6\xa8\xb5\xc4 DNS \xba\xf3\xd7\xba . . . . . . . : \r\n\r\n\xcb\xed\xb5\xc0\xca\xca\xc5\xe4\xc6\xf7 Teredo Tunneling Pseudo-Interface:\r\n\r\n \xc1\xac\xbd\xd3\xcc\xd8\xb6\xa8\xb5\xc4 DNS \xba\xf3\xd7\xba . . . . . . . : \r\n IPv6 \xb5\xd8\xd6\xb7 . . . . . . . . . . . . : 2001:0:9d38:6ab8:242a:88b7:20b7:be6c\r\n \xb1\xbe\xb5\xd8\xc1\xb4\xbd\xd3 IPv6 \xb5\xd8\xd6\xb7. . . . . . . . : fe80::242a:88b7:20b7:be6c%14\r\n \xc4\xac\xc8\xcf\xcd\xf8\xb9\xd8. . . . . . . . . . . . . : ::\r\n‘
stderr = obj.stderr.read() # stdout3--->: ‘xxxxxipconfig‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。
#3、把命令结果返回给客户端;
conn.send(stdout+stderr)#+号是一个可以优化的点子;
except ConnectionResetError:#适用于Windows操作系统;
break
conn.close()
phone.close()
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect((‘127.0.0.1‘,18080))#ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。
while True:
#发送命令;
cmd = input(‘>>>:‘).strip()
if not cmd:continue
phone.send(cmd.encode(‘utf-8‘))
#2、拿到命令的结果
data = phone.recv(1024)
print(data.decode(‘gbk‘))
phone.close()
"""
C:\Users\Administrator\PycharmProjects\LFXC2018\venv\Scripts\python.exe "C:/Users/Administrator/PycharmProjects/LFXC2018/第三模块 面向对象/网络编程/11-模拟ssh远程执行命令-代码实现/11-client.py"
>>>:ipconfig
Windows IP 配置
以太网适配器 以太网 2:
连接特定的 DNS 后缀 . . . . . . . :
本地链接 IPv6 地址. . . . . . . . : fe80::fdc4:7f23:1928:6026%11
IPv4 地址 . . . . . . . . . . . . : 192.168.1.5
子网掩码 . . . . . . . . . . . . : 255.255.255.0
默认网关. . . . . . . . . . . . . : fe80::1%11
192.168.1.1
以太网适配器 以太网 3:
媒体状态 . . . . . . . . . . . . : 媒体已断开连接
连接特定的 DNS 后缀 . . . . . . . :
隧道适配器 Teredo Tunneling Pseudo-Interface:
连接特定的 DNS 后缀 . . . . . . . :
IPv6 地址 . . . . . . . . . . . . : 2001:0:9d38:6ab8:242a:88b7:20b7:be6c
本地链接 IPv6 地址. . . . . . . . : fe80::242a:88b7:20b7:be6c%14
默认网关. . . . . . . . . . . . . : ::
>>>:
"""
某个命令的输出结果字节比较长,但客户端只recv(1024), 可结果比1024长呀,那怎么办,只好在服务器端的IO缓冲区里把客户端还没收走的暂时存下来,等客户端下次再来收。同志们,这个现象叫做粘包,就是指两次结果粘到一起了。它的发生主要是因为socket缓冲区导致的,来看一下


还是看上图,发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体,或说是一个流(stream),一条消息有多少字节对应用程序是不可见的,因此TCP协议是面向流的协议,这也是容易出现粘包问题的原因。而UDP是面向消息的协议,每个UDP段都是一条消息,应用程序必须以消息为单位提取数据,不能一次提取任意字节的数据,这一点和TCP是很不同的。怎样定义消息呢?可以认为对方一次性write/send的数据为一个消息,需要明白的是当对方send一条信息的时候,无论底层怎样分段分片,TCP协议层会把构成整条消息的数据段排序完成后才呈现在内核缓冲区。
所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# __Author__:TQTL911
# Version:python3.6.6
# Time:2018/7/14 16:11
import socket
import subprocess
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind((‘127.0.0.1‘,9901))#0~65525,其中0~1024给操作系统使用;
phone.listen(5)#5表示最大挂起的链接数;
print(‘starting...‘)
while True:#链接循环
conn,client_addr = phone.accept()
print(client_addr)
while True:#通信循环
try:
#1、接收命令;
cmd = conn.recv(1024)#接收数据的最大字节数;1、单位:bytes;2、最大接收1024个bytes;
#if not cmd:break#仅适用于Linux操作系统
#2、执行命令,拿到结果并打印;
obj = subprocess.Popen(cmd.decode(‘utf-8‘),shell=True,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE)
stdout = obj.stdout.read()
stderr = obj.stderr.read()
#3、把命令的结果返回给客户端;
print(len(stdout)+ len(stderr))
conn.send(stdout + stderr)#+号是一个可以优化的点
except ConnectionResetError:#异常处理;
break
conn.close()
phone.close()
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# __Author__:TQTL911
# Version:python3.6.6
# Time:2018/7/14 16:17
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect((‘127.0.0.1‘,9901))#0~65525,其中0~1024给操作系统使用;
while True:
#1、发送命令;
cmd = input(‘>>:‘).strip()#ls /etc
if not cmd:continue
phone.send(cmd.encode(‘utf-8‘))
#2、拿到命令结果;
data = phone.recv(1024)#有可能数据包的大小超过1024bytes;
print(data.decode(‘gbk‘))
phone.close()
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:2018/7/14 16:11 import socket import subprocess server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind((‘127.0.0.1‘,9001))#0~65525,其中0~1024给操作系统使用; server.listen(5)#5表示最大挂起的链接数; conn,addr = server.accept() res1 = conn.recv(1024) print(‘第1次‘,res1) res2 = conn.recv(1024) print(‘第2次‘,res2)
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:2018/7/14 16:17 import socket import time client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect((‘127.0.0.1‘,9001)) client.send(‘hello‘.encode(‘utf-8‘)) time.sleep(5) client.send(‘world‘.encode(‘utf-8‘))

1)server.py
import socket
import os
import subprocess
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind((‘127.0.0.1‘,18080))#0~65535,其中0~1024,系统使用;
phone.listen(5)
print(‘starting....‘)
while True:#链接循环;
conn,client_addr = phone.accept()
print(client_addr)
while True:#进入通信循环;
try:
#1、收命令;
cmd = conn.recv(1024)#1、单位bytes;2、1024代表最大接受1024个bytes;
if not cmd:break#仅适用于Linux操作系统;
print(‘客户端数据‘,cmd)
#2、执行命令,拿到结果;
obj = subprocess.Popen(cmd.decode(‘utf-8‘), shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
# obj = subprocess.Popen(‘xxxxxipconfig‘,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
stdout = obj.stdout.read() # stdout1--->: b‘\r\nWindows IP \xc5\xe4\xd6\xc3\r\n\r\n\r\n\xd2\xd4\xcc\xab\xcd\xf8\xca\xca\xc5\xe4\xc6\xf7 \xd2\xd4\xcc\xab\xcd\xf8 2:\r\n\r\n \xc1\xac\xbd\xd3\xcc\xd8\xb6\xa8\xb5\xc4 DNS \xba\xf3\xd7\xba . . . . . . . : \r\n \xb1\xbe\xb5\xd8\xc1\xb4\xbd\xd3 IPv6 \xb5\xd8\xd6\xb7. . . . . . . . : fe80::fdc4:7f23:1928:6026%11\r\n IPv4 \xb5\xd8\xd6\xb7 . . . . . . . . . . . . : 192.168.1.5\r\n \xd7\xd3\xcd\xf8\xd1\xda\xc2\xeb . . . . . . . . . . . . : 255.255.255.0\r\n \xc4\xac\xc8\xcf\xcd\xf8\xb9\xd8. . . . . . . . . . . . . : fe80::1%11\r\n 192.168.1.1\r\n\r\n\xd2\xd4\xcc\xab\xcd\xf8\xca\xca\xc5\xe4\xc6\xf7 \xd2\xd4\xcc\xab\xcd\xf8 3:\r\n\r\n \xc3\xbd\xcc\xe5\xd7\xb4\xcc\xac . . . . . . . . . . . . : \xc3\xbd\xcc\xe5\xd2\xd1\xb6\xcf\xbf\xaa\xc1\xac\xbd\xd3\r\n \xc1\xac\xbd\xd3\xcc\xd8\xb6\xa8\xb5\xc4 DNS \xba\xf3\xd7\xba . . . . . . . : \r\n\r\n\xcb\xed\xb5\xc0\xca\xca\xc5\xe4\xc6\xf7 Teredo Tunneling Pseudo-Interface:\r\n\r\n \xc1\xac\xbd\xd3\xcc\xd8\xb6\xa8\xb5\xc4 DNS \xba\xf3\xd7\xba . . . . . . . : \r\n IPv6 \xb5\xd8\xd6\xb7 . . . . . . . . . . . . : 2001:0:9d38:6ab8:242a:88b7:20b7:be6c\r\n \xb1\xbe\xb5\xd8\xc1\xb4\xbd\xd3 IPv6 \xb5\xd8\xd6\xb7. . . . . . . . : fe80::242a:88b7:20b7:be6c%14\r\n \xc4\xac\xc8\xcf\xcd\xf8\xb9\xd8. . . . . . . . . . . . . : ::\r\n‘
stderr = obj.stderr.read() # stdout3--->: ‘xxxxxipconfig‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。
#3、把命令结果返回给客户端;
#3-1把数据的长度发给客户端;
#3-2再发送真实的数据
#把报头(固定长度)发送给客户端;
total_size = print(len(stdout)+len(stderr))
conn.send(str(total_size).encode(‘utf-8‘))
#conn.send(stdout+stderr)#+号是一个可以优化的点子;
conn.send(stdout)
conn.send(stderr)
except ConnectionResetError:#适用于Windows操作系统;
break
conn.close()
phone.close()
2)client.py
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect((‘127.0.0.1‘,18080))#ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。
while True:
cmd = input(‘>>>:‘).strip()
if not cmd:continue
phone.send(cmd.encode(‘utf-8‘))
total_size =102400
#第一步,先拿到数据的长度;
#接受真实的数据;
recv_size = 0
recv_data = b‘‘
while recv_size < total_size:
res = phone.recv(1024)
recv_data += res
recv_size += len(res)
print(recv_data.decode(‘utf-8‘))
phone.close()
1、简单版本;
1)、sever.py
import socket
import os
import subprocess
import struct
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind((‘127.0.0.1‘,18081))#0~65535,其中0~1024,系统使用;
phone.listen(5)
print(‘starting....‘)
while True:#链接循环;
conn,client_addr = phone.accept()
print(client_addr)
while True:#进入通信循环;
try:
#1、收命令;
cmd = conn.recv(1024)#1、单位bytes;2、1024代表最大接受1024个bytes;
if not cmd:break#仅适用于Linux操作系统;
print(‘客户端数据‘,cmd)
#2、执行命令,拿到结果;
obj = subprocess.Popen(cmd.decode(‘utf-8‘), shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
# obj = subprocess.Popen(‘xxxxxipconfig‘,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
stdout = obj.stdout.read() # stdout1--->: b‘\r\nWindows IP \xc5\xe4\xd6\xc3\r\n\r\n\r\n\xd2\xd4\xcc\xab\xcd\xf8\xca\xca\xc5\xe4\xc6\xf7 \xd2\xd4\xcc\xab\xcd\xf8 2:\r\n\r\n \xc1\xac\xbd\xd3\xcc\xd8\xb6\xa8\xb5\xc4 DNS \xba\xf3\xd7\xba . . . . . . . : \r\n \xb1\xbe\xb5\xd8\xc1\xb4\xbd\xd3 IPv6 \xb5\xd8\xd6\xb7. . . . . . . . : fe80::fdc4:7f23:1928:6026%11\r\n IPv4 \xb5\xd8\xd6\xb7 . . . . . . . . . . . . : 192.168.1.5\r\n \xd7\xd3\xcd\xf8\xd1\xda\xc2\xeb . . . . . . . . . . . . : 255.255.255.0\r\n \xc4\xac\xc8\xcf\xcd\xf8\xb9\xd8. . . . . . . . . . . . . : fe80::1%11\r\n 192.168.1.1\r\n\r\n\xd2\xd4\xcc\xab\xcd\xf8\xca\xca\xc5\xe4\xc6\xf7 \xd2\xd4\xcc\xab\xcd\xf8 3:\r\n\r\n \xc3\xbd\xcc\xe5\xd7\xb4\xcc\xac . . . . . . . . . . . . : \xc3\xbd\xcc\xe5\xd2\xd1\xb6\xcf\xbf\xaa\xc1\xac\xbd\xd3\r\n \xc1\xac\xbd\xd3\xcc\xd8\xb6\xa8\xb5\xc4 DNS \xba\xf3\xd7\xba . . . . . . . : \r\n\r\n\xcb\xed\xb5\xc0\xca\xca\xc5\xe4\xc6\xf7 Teredo Tunneling Pseudo-Interface:\r\n\r\n \xc1\xac\xbd\xd3\xcc\xd8\xb6\xa8\xb5\xc4 DNS \xba\xf3\xd7\xba . . . . . . . : \r\n IPv6 \xb5\xd8\xd6\xb7 . . . . . . . . . . . . : 2001:0:9d38:6ab8:242a:88b7:20b7:be6c\r\n \xb1\xbe\xb5\xd8\xc1\xb4\xbd\xd3 IPv6 \xb5\xd8\xd6\xb7. . . . . . . . : fe80::242a:88b7:20b7:be6c%14\r\n \xc4\xac\xc8\xcf\xcd\xf8\xb9\xd8. . . . . . . . . . . . . : ::\r\n‘
stderr = obj.stderr.read() # stdout3--->: ‘xxxxxipconfig‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。
#3、把命令结果返回给客户端;
total_size = print(len(stdout) + len(stderr))
header = struct.pack(‘i‘,total_size)
#第1步:制作固定长度的报头;
conn.send(header)
# 第2步:把报头发送给客户端;
conn.send(str(total_size).encode(‘utf-8‘))
# 第3步:再发送真实的数据;
conn.send(stdout)
conn.send(stderr)
except ConnectionResetError:#适用于Windows操作系统;
break
conn.close()
phone.close()
2)、struct模块的使用
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:Python3.6.5 # Date:2018/6/23 0023 9:32 import struct res = struct.pack(‘i‘,1230) print(res,type(res),len(res)) #client.recv(4) obj = struct.unpack(‘i‘,res) print(obj[0])
3)、client.py的使用
import socket
import struct
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect((‘127.0.0.1‘,18081))#ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。
while True:
#1、发送命令;
cmd = input(‘>>>:‘).strip()
if not cmd:continue
phone.send(cmd.encode(‘utf-8‘))
#2、拿到命令的结果,并打印;
#第1步:先收报头;
header = phone.recv(4)
# 第2步,从报头中解析出真实的数据;
total_size = struct.unpack(‘i‘,header)[0]
# 第2步:接受真实的数据;
recv_size = 0
recv_data = b‘‘
while recv_size < total_size:
res = phone.recv(1024)
recv_data += res
recv_size += len(res)
print(recv_data.decode(‘utf-8‘))
phone.close()
1)、server.py
import socket
import os
import subprocess
import struct
import json
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind((‘127.0.0.1‘,18080))#0~65535,其中0~1024,系统使用;
phone.listen(5)
print(‘starting....‘)
while True:#链接循环;
conn,client_addr = phone.accept()
print(client_addr)
while True:#进入通信循环;
try:
#1、收命令;
cmd = conn.recv(8096)#1、单位bytes;2、1024代表最大接受1024个bytes;
if not cmd:break#仅适用于Linux操作系统;
#2、执行命令,拿到结果;
obj = subprocess.Popen(cmd.decode(‘utf-8‘), shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
# obj = subprocess.Popen(‘xxxxxipconfig‘,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
stdout = obj.stdout.read() # stdout1--->: b‘\r\nWindows IP \xc5\xe4\xd6\xc3\r\n\r\n\r\n\xd2\xd4\xcc\xab\xcd\xf8\xca\xca\xc5\xe4\xc6\xf7 \xd2\xd4\xcc\xab\xcd\xf8 2:\r\n\r\n \xc1\xac\xbd\xd3\xcc\xd8\xb6\xa8\xb5\xc4 DNS \xba\xf3\xd7\xba . . . . . . . : \r\n \xb1\xbe\xb5\xd8\xc1\xb4\xbd\xd3 IPv6 \xb5\xd8\xd6\xb7. . . . . . . . : fe80::fdc4:7f23:1928:6026%11\r\n IPv4 \xb5\xd8\xd6\xb7 . . . . . . . . . . . . : 192.168.1.5\r\n \xd7\xd3\xcd\xf8\xd1\xda\xc2\xeb . . . . . . . . . . . . : 255.255.255.0\r\n \xc4\xac\xc8\xcf\xcd\xf8\xb9\xd8. . . . . . . . . . . . . : fe80::1%11\r\n 192.168.1.1\r\n\r\n\xd2\xd4\xcc\xab\xcd\xf8\xca\xca\xc5\xe4\xc6\xf7 \xd2\xd4\xcc\xab\xcd\xf8 3:\r\n\r\n \xc3\xbd\xcc\xe5\xd7\xb4\xcc\xac . . . . . . . . . . . . : \xc3\xbd\xcc\xe5\xd2\xd1\xb6\xcf\xbf\xaa\xc1\xac\xbd\xd3\r\n \xc1\xac\xbd\xd3\xcc\xd8\xb6\xa8\xb5\xc4 DNS \xba\xf3\xd7\xba . . . . . . . : \r\n\r\n\xcb\xed\xb5\xc0\xca\xca\xc5\xe4\xc6\xf7 Teredo Tunneling Pseudo-Interface:\r\n\r\n \xc1\xac\xbd\xd3\xcc\xd8\xb6\xa8\xb5\xc4 DNS \xba\xf3\xd7\xba . . . . . . . : \r\n IPv6 \xb5\xd8\xd6\xb7 . . . . . . . . . . . . : 2001:0:9d38:6ab8:242a:88b7:20b7:be6c\r\n \xb1\xbe\xb5\xd8\xc1\xb4\xbd\xd3 IPv6 \xb5\xd8\xd6\xb7. . . . . . . . : fe80::242a:88b7:20b7:be6c%14\r\n \xc4\xac\xc8\xcf\xcd\xf8\xb9\xd8. . . . . . . . . . . . . : ::\r\n‘
stderr = obj.stderr.read() # stdout3--->: ‘xxxxxipconfig‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。
#3、把命令结果返回给客户端;
# 第1步:制作固定长度的报头;
header_dic = {
‘filename‘:‘a.txt‘,
‘md5‘:‘xxxx‘,
‘total_size‘:len(stdout) + len(stderr)
}
header_json = json.dumps(header_dic)
header_bytes = header_json.encode(‘utf-8‘)
# 第2步:先发送报头的长度;
conn.send(struct.pack(‘i‘,len(header_bytes)))
# 第3步:把报头发送给客户端;
conn.send(header_bytes)
# 第4步:再发送真实的数据;
conn.send(stdout)
conn.send(stderr)
except ConnectionResetError:#适用于Windows操作系统;
break
conn.close()
phone.close()
2)、client.py
import socket
import struct
import json
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect((‘127.0.0.1‘,18080))#ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。
while True:
#1、发送命令;
cmd = input(‘>>>:‘).strip()
if not cmd:continue
phone.send(cmd.encode(‘utf-8‘))
#2、拿到命令的结果,并打印;
#第1步:先收报头的长度;
obj = phone.recv(4)
header_size = struct.unpack(‘i‘,obj)[0]
#第2步,再收报头;
header_bytes = phone.recv(header_size)
#第3步,从报头中解析出真实的数据的描述信息;
header_json= header_bytes.decode(‘utf-8‘)
header_dic = header_json.loads(header_json)
print(header_dic)
total_size = header_dic[‘total_size‘]
# 第4步:接受真实的数据;
recv_size = 0
recv_data = b‘‘
while recv_size < total_size:
res = phone.recv(1024)
recv_data += res
recv_size += len(res)
print(recv_data.decode(‘utf-8‘))
phone.close()
3)、struct.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:Python3.6.5
# Date:2018/6/23 0023 9:32
import struct
import json
header_dic = {
‘filename‘: ‘a.txt‘,
‘md5‘: ‘xxxx‘,
‘total_size‘: 33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
}
header_json = json.dumps(header_dic)
#print(header_json,type(header_json))#{"filename": "a.txt", "md5": "xxxx", "total_size": 33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333} <class ‘str‘>
header_bytes = header_json.encode(‘utf-8‘)
print(type(header_bytes))#<class ‘bytes‘>
print(len(header_bytes))#171
# res = struct.pack(‘i‘,1230)
# print(res,type(res),len(res))
# #client.recv(4)
# obj = struct.unpack(‘i‘,res)
# print(obj[0])
res = struct.pack(‘l‘,len(header_bytes))
print(res,len(res))
1)、server.py
import socket
import os
import subprocess
import struct
import json
share_dir = r‘C:\Users\Administrator\PycharmProjects\LFXC2018\第三模块 面向对象\网络编程\17-文件传输功能实现\server\share‘
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind((‘127.0.0.1‘,28080))#0~65535,其中0~1024,系统使用;
phone.listen(5)
print(‘starting....‘)
while True:#链接循环;
conn,client_addr = phone.accept()
print(client_addr)
while True:#进入通信循环;
try:
#1、收命令;
res = conn.recv(8096)#1、单位bytes;2、1024代表最大接受1024个bytes;
if not res:break#仅适用于Linux操作系统;
#2、解析命令,提取相应命令参数;
cmds = res.decode(‘utf-8‘).split()#[‘get‘,‘a.txt‘]
filename = cmds[1]
#3、以读的方式打开文件,读取文件内容,发送给客户端;
# 第1步:制作固定长度的报头;
header_dic = {
‘filename‘:filename,#‘filename‘:‘xxx‘
‘md5‘:‘xxdxxx‘,
‘file_size‘:os.path.getsize(r‘%s\%s‘%(share_dir,filename))
}
header_json = json.dumps(header_dic)
header_bytes = header_json.encode(‘utf-8‘)
# 第2步:先发送报头的长度;
conn.send(struct.pack(‘i‘,len(header_bytes)))
# 第3步:把报头发送给客户端;
conn.send(header_bytes)
# 第4步:再发送真实的数据;
with open(‘%s\%s‘%(share_dir,filename),‘rb‘) as f:
#conn.send(f.read())#避免使用该方法,大文件将会占用过多内存;
for line in f:#节省内存的方案;
conn.send(line)
except ConnectionResetError:#适用于Windows操作系统;
break
conn.close()
phone.close()
2)、client.py
import socket
import struct
import json
download_dir =r‘C:\Users\Administrator\PycharmProjects\LFXC2018\第三模块 面向对象\网络编程\17-文件传输功能实现\client\download‘
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect((‘127.0.0.1‘,28080))#ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。
while True:
#1、发送命令;
cmd = input(‘>>>:‘).strip()#get a.txt
if not cmd:continue
phone.send(cmd.encode(‘utf-8‘))
#2、以写的方式打开一个新文件,接收服务端发来的文件的内容写入客户的新文件;
#第1步:先收报头的长度;
obj = phone.recv(4)
header_size = struct.unpack(‘i‘,obj)[0]
#第2步,再收报头;
header_bytes = phone.recv(header_size)
#第3步,从报头中解析出真实的数据的描述信息;
header_json= header_bytes.decode(‘utf-8‘)
header_dic = json.loads(header_json)
print(header_dic)
total_size = header_dic[‘file_size‘]
filename = header_dic[‘filename‘]
# 第4步:接收真实的数据;
with open(‘%s\%s‘%(download_dir,filename),‘wb‘) as f:
recv_size = 0
while recv_size < total_size:
line = phone.recv(1024)
f.write(line)
recv_size += len(line)
print(‘总大小%s 已下载大小:%s‘%(total_size,recv_size))
phone.close()
3)、struct.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:Python3.6.5
# Date:2018/6/23 0023 9:32
import struct
import json
header_dic = {
‘filename‘: ‘a.txt‘,
‘md5‘: ‘xxxx‘,
‘total_size‘: 33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
}
header_json = json.dumps(header_dic)
#print(header_json,type(header_json))#{"filename": "a.txt", "md5": "xxxx", "total_size": 33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333} <class ‘str‘>
header_bytes = header_json.encode(‘utf-8‘)
print(type(header_bytes))#<class ‘bytes‘>
print(len(header_bytes))#171
# res = struct.pack(‘i‘,1230)
# print(res,type(res),len(res))
# #client.recv(4)
# obj = struct.unpack(‘i‘,res)
# print(obj[0])
res = struct.pack(‘l‘,len(header_bytes))
print(res,len(res))
【python】第三模块:面向对象&网络编程基础 第2章 网络编程
原文:https://www.cnblogs.com/bruce-blogs/p/11306429.html