网络编程

一.网络编程的内容
网络编程的协议:

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


 

posted on 2018-05-29 10:26  风度翩翩的机器空  阅读(132)  评论(0编辑  收藏  举报

导航