day 08 初识网络编程

  刚刚结束面向对象,换了新老师,讲网络编程。收获的话,从实际意义明白了网络连接,收发啊的细节。聊天:

import socket

sock = socket.socket()
sock.connect(('127.0.0.1',8800))

while 1:
    first = sock.recv(1024)
    print(first.decode('utf-8'))
    cont = input('输入:')
    sock.sendall(cont.encode('utf-8'))
    if cont == 'q':
        break
    message = sock.recv(1024)
    if message.decode('utf-8') == 'q':
        print('对方断开')
        break
    print('收到:',message.decode('utf-8'))
sock.close()
聊天-client
import socket
#
# sock = socket.socket()
# sock.bind(('127.0.0.1',8800))
# sock.listen(5)
# conn , addr = sock.accept()
# print('连接已建立')
# conn.sendall('欢迎'.encode('utf-8'))
# data = conn.recv(1024)
# print('收到:',data.decode('utf-8'))
# conn.sendall('开始聊天吧'.encode('utf-8'))
# print('聊天开始'.center(20,'-'))
# while 1:
#     content = input('输入:')
#     conn.sendall(content.encode('utf-8'))
#     message = conn.recv(1024)
#     print('收到:',message.decode('utf-8'))

'''
可退出版
'''

import socket

sock = socket.socket()
sock.bind(('127.0.0.1',8800))
sock.listen(5)


while 1:
    print('server is working...')
    conn, addr = sock.accept()
    print('连接已建立')
    while 1:
        try:
            conn.sendall('欢迎'.encode('utf-8'))
            message = conn.recv(1024)
            if message.decode('utf-8') == 'q':
                print('对方断开连接')
                break
            print('收到了:', message.decode('utf-8'))
            response = input('输入:').encode('utf-8')
            conn.sendall(response)
            if response.decode('utf-8') == 'q':
                break
        except Exception as e:
            break
    conn.close()
聊天-server

重点的话,在于了解收发的对应吧,还有一些异常的处理

ssh:

import socket
import struct
sock = socket.socket()
sock.connect(('127.0.0.1',8800))
first = sock.recv(1024)
print(first.decode('utf-8'))

while 1:

    cmd = input('>>>')
    sock.sendall(cmd.encode('utf-8'))
    if cmd == 'q':
        break
    if len(cmd) == 0:
        continue
    header = sock.recv(4)
    data_len = struct.unpack('i',header)[0]
    if not data_len:
        print('输入命令有误,请重输!')
        continue
    print('数据长度:',data_len)
    recv_data = b''
    has_recv_len = 0
    while has_recv_len < data_len:
        message = sock.recv(1024)
        recv_data += message
        has_recv_len += len(message)
    print('收到:',recv_data.decode('gbk'))
sock.close()
ssh client
import struct
import socket
import subprocess
sock = socket.socket()
sock.bind(('127.0.0.1',8800))
sock.listen(5)

while 1:
    print('server is working...')
    conn, addr = sock.accept()
    print('连接已建立')
    conn.sendall('欢迎'.center(10,'-').encode('utf-8'))
    while 1:
        try:
            message = conn.recv(1024)
            s = message.decode('utf-8')
            if s == 'q':
                print('对方断开连接')
                break
            print(s)
            a = subprocess.Popen(s, shell=True,
            stderr=subprocess.PIPE, stdout=subprocess.PIPE)
            reaction = a.stdout.read()
            print('len',len(reaction))
            reaction_len = struct.pack('i',len(reaction))
            conn.sendall(reaction_len)
            conn.sendall(reaction)
        except Exception as e:
            break
    conn.close()
ssh server

重点是了解黏包,并解决,这里用到两个新东西,struct和subprocess

再到ftp:0.5版本,参照之前的思路,实现了上传这一个功能。

import socket
import os
import json
import struct
sock = socket.socket()
sock.connect(('127.0.0.1',8800))
print('已连接ftp服务器...')

cmd = input('输入操作及文件路径')
operation,file_name = cmd.split('|')
file_size = os.path.getsize(file_name)

head = {'操作':operation,
             '文件名称':file_name,
             '文件大小':file_size}
head_json = json.dumps(head)
head_len = struct.pack('i',len(head_json))
sock.sendall(head_len)
sock.sendall(head_json.encode('utf-8'))
with open(file_name,'rb') as f:
    for line in f:
        sock.sendall(line)
ftp 0.5 client
import socket
import json
import struct

sock = socket.socket()
sock.bind(('127.0.0.1',8800))
sock.listen(5)
while 1:
    print('server is working...')
    conn,addr = sock.accept()
    print('有客户端接入')

    while 1:
        try:
            head_len = struct.unpack('i',conn.recv(4))[0]
            print(head_len)
            head_json = conn.recv(head_len)
            head = json.loads(head_json.decode('utf-8'))
            print(head)
            file_size = head['文件大小']
            file_name = head['文件名称']
            print(file_size)
            recv_data = b''
            with open('putdir/'+ file_name,'wb') as f:
                has_recv_len = 0
                while has_recv_len < file_size:
                    data = conn.recv(1024)
                    recv_data += data
                    has_recv_len += len(data)
                    f.write(data)
        except Exception as e:
            break
ftp 0.5 server

然后是1.0版本,用了面向对象,有用户登录,上传下载,而且比较满意的是 异常的处理和条件的判断

import socket
import json
import struct
import sys
import os
base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(base_path)

from core import auth
from tool import mkdir

class Ftp_client:
    ret = auth.login()
    def __init__(self,ip_port):
        '''
        负责初始化操作,
        :param ip_port:
        '''
        self.sock = socket.socket()
        self.address = ip_port
            #登录
        if Ftp_client.ret:
            folder_path = os.path.join(base_path,Ftp_client.ret['name'])
            mkdir.mkdir(folder_path) #登录成功创建一个属于该用户的文件夹
            try:
                self.client_connect()
            except:
                self.client_close()
                raise


    def client_connect(self):
        self.sock.connect(self.address)
    def client_close(self):
        self.sock.close()



    def run(self):
        '''
        登陆成功后,执行客户端操作
        :return:
        '''
        while 1:
            cmd = input('请输入:(格式:操作|文件)\n').strip()
            if not cmd:
                continue
            try:
                operation,filename = cmd.split('|')
            except ValueError:
                print('未按照格式输入')
                continue
            if hasattr(self, operation):
                #print(operation)
                self.sock.sendall(cmd.encode('utf-8'))
                getattr(self, operation)(filename)
            else:
                print('没有此操作')

    def put(self,file):
        '''
        上传文件
        :param file:
        :return:
        '''
        file_path = os.path.join(base_path,'db',file)
        if not os.path.isfile(file_path):
            print('文件:%s 不存在' % file_path)
            return
        else:
            filesize = os.path.getsize(file_path)

        head = {'文件名称': file,
                '文件大小': filesize}
        head_json = json.dumps(head)
        head_len = struct.pack('i', len(head_json))
        self.sock.sendall(head_len)
        self.sock.sendall(head_json.encode('utf-8'))
        with open(file_path, 'rb') as f:
            for line in f:
                self.sock.sendall(line)
            print('上传完成')

    def get(self,file):
        '''
        下载文件
        :param file:
        :return:
        '''
        head_len = struct.unpack('i', self.sock.recv(4))[0]
        #print(head_len)
        head_json = self.sock.recv(head_len)
        head = json.loads(head_json.decode('utf-8'))
        #print(head)

        file_size = head['文件大小']
        file_name = head['文件名称']
        #print(file_size)
        if head['文件存在状态']:#
            print('开始下载')
            recv_data = b''
            with open(os.path.join(base_path,Ftp_client.ret['name'], file_name), 'wb') as f:
                has_recv_len = 0
                while has_recv_len < file_size:
                    data = self.sock.recv(1024)
                    recv_data += data
                    has_recv_len += len(data)
                    f.write(data)
            print('下载完成')
        else:
            print('您要下载的文件不存在!')



a = Ftp_client(('127.0.0.1',8800))
a.run()
ftp 1.0 client
import socket
import json
import os,sys
import struct
import socketserver
import os
import sys
base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(base_path)


class Ftp_Server:
    def __init__(self,ip_port):
        self.sock = socket.socket()
        self.address = ip_port

        try:
            self.server_bind()
            self.server_listen()
        except:
            self.server_close()
            raise
    def server_bind(self):
        self.sock.bind(self.address)
    def server_listen(self):
        self.sock.listen(5)
    def server_accept(self):
        return self.sock.accept()
    def server_close(self):
        self.sock.close()


    def run(self):
        while 1:
            print('server is working...')
            self.conn,self.addr = self.server_accept()
            print('from client',self.addr)
            while 1:
                try:
                    cmd = self.conn.recv(1024).decode()
                    print(cmd)
                    operation,filename = cmd.split('|')
                    getattr(self,operation)(filename)

                except Exception:
                    break


    def put(self,file):
        '''
        对应用户的上传
        :param file:
        :return:
        '''
        head_len = struct.unpack('i', self.conn.recv(4))[0]
        print(head_len)
        head_json = self.conn.recv(head_len)
        head = json.loads(head_json.decode('utf-8'))
        print(head)
        file_size = head['文件大小']
        file_name = head['文件名称']
        print(file_size)
        recv_data = b''
        file_path = os.path.join(base_path,'cloud',file_name)
        print(file_path)
        with open(file_path, 'wb') as f:
            has_recv_len = 0
            while has_recv_len < file_size:
                data = self.conn.recv(1024)
                recv_data += data
                has_recv_len += len(data)
                f.write(data)

    def get(self,file):
        '''
        对应用户的下载
        :param file:
        :return:
        '''
        status = True       #文件是否存在的状态标志
        file_path = os.path.join(base_path,'home',file)#拼出文件完整目录
        if not os.path.isfile(file_path):
            status = False
            filesize = 0
        else:
            filesize = os.path.getsize(file_path)
        print(status,111)
        head = {'文件存在状态':status,
                '文件名称': file,
                '文件大小': filesize}

        head_json = json.dumps(head)
        head_len = struct.pack('i', len(head_json))
        self.conn.sendall(head_len)
        self.conn.sendall(head_json.encode('utf-8'))
        if status:
            with open(file_path, 'rb') as f:
                for line in f:
                    self.conn.sendall(line)
        else:
            return

a = Ftp_Server(('127.0.0.1',8800))
a.run()
ftp 1.0 server

缺点是没能并发,多个用户,主要是socketserver 没看懂。

网络编程开始,代码的量就一下上来了。一是有两个文件client和server,二是收发的信息又是会重复

总体我还是很满意这次的作业,从一开始毫无思路,到面向过程写上传,再到看懂面向对象,再到自己调试,程序越来越健壮。

 

posted @ 2018-09-17 16:06  CP喜欢晒太阳  阅读(68)  评论(0)    收藏  举报