一.网络编程的内容
网络编程的协议:
1.UDP
2.TCP
网络编程的关键步骤:
确定对端IP地址——>确定应用程序端口——>确定通信协议
TCP服务端和TCP客户端
family = AF_INET:服务器之间的通信
family = AF_INET6:服务器之间的通信
family = AF_UNIX:Unix不同进程之间的通信
server下的方法
bind()
listen()
accept()
recv()
send(string)
sendall(将send放在一个循环里)# 传送的内容必须是bytes类型
close()
client下的方法
connect()
recv()
send(string)
sendall(将send放在一个循环里)# 传送的内容必须是bytes类型
close()
**注意一收一发(一次发送对应一次接收)
二.网络编程的示例
1.简单实现命令行的指令执行
server:
import socket
import subprocess
sk = socket.socket()
dress = ('127.0.0.1', 8000)
sk.bind(dress)
sk.listen(3)
while True:
# conn是客户端的socket的对象,接受客户端
conn, addr = sk.accept()
while True:
# 接受消息
try:
data = str(conn.recv(1024), 'utf8')
except ConnectionResetError:
break
if not data: break
# 在命令行执行data,stdout参数将子进程挪到主进程,否则自动执行并且进行标准输出
# 另外obj也会得不到子进程的内容
obj = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE)
cmd_result = obj.stdout.read()
# 将结果的长度发过去
result_len = bytes(str(len(cmd_result)), 'utf8')
# 粘包现象(cpu处理速度太快,连续发送的数据可能连在一起),可以加入recv来阻塞
conn.sendall(result_len)
conn.recv(1024)
conn.sendall(cmd_result)
sk.close()
client:
import socket
sk = socket.socket()
dress = ('127.0.0.1', 8000)
sk.connect(dress)
while True:
# 发送消息
inp = input('>>:')
if inp == 'exit':break
sk.send(bytes(inp, 'utf8'))
result_len = int(str(sk.recv(1024), 'utf8'))
# 解决粘包
sk.sendall('you can send again')
data = bytes() # 阻塞
# 接受消息,如果长度不等于接受的长度,就继续接受
while len(data) != result_len:
data += sk.recv(1024) # 阻塞
print(str(data, 'gbk'))
sk.close()
2.实现文件的上传
server:
import socket
import os
sk = socket.socket()
dress = ('127.0.0.1', 8000)
sk.bind(dress)
sk.listen(3)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
while True:
# 接收命令和文件信息
conn, addr = sk.accept()
data = str(conn.recv(1024), 'utf8')
cmd, filename, filesize = data.split('|')
path = os.path.join(BASE_DIR, 'lql', filename)
filesize = int(filesize)
# 接受文件并且写入
has_receive = 0
with open(path, 'ab') as f:
while has_receive!=filesize:
data = conn.recv(1024)
f.write(data)
has_receive += len(data)
print('写入成功')
sk.close()
client:
import socket
import os
sk = socket.socket()
dress = ('127.0.0.1', 8000)
sk.connect(dress)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
while True:
inp = input('>>:').strip() # 输入命令和文件名
cmd, path = inp.split('|')
path = os.path.join(BASE_DIR, path)
# 传命令和文件信息
filename = os.path.basename(path)
filesize = os.stat(path).st_size
file_info = 'post|%s|%s' % (filename, filesize)
sk.sendall(bytes(file_info, 'utf8'))
# 传文件
has_sent = 0
with open(path, 'rb') as f:
while has_sent != filesize:
data = f.read(1024)
sk.sendall(data)
has_sent += len(data)
print('上传成功')
sk.close()
三.socketserver模块
server:
import socket
sk = socket.socket()
adress = ('127.0.0.1', 8000)
sk.connect(adress)
print('客户端启动...')
while True:
inp = input('>>:')
if inp == 'exit':break
sk.send(bytes(inp, 'utf8'))
data = sk.recv(1024) # 阻塞
print(str(data, 'utf8') )
sk.close()