3W作业_极简交互式网络笔记

本周整体任务概述:

- 在上周开发基础上, 完成 极简交互式笔记的网络版本
- 需求如下:
    - 每次运行时合理的打印出过往的所有笔记
    - 一次接收输入一行笔记
    - 在服务端保存为文件:
        - 在所有访问的客户端可以获得历史笔记
    - 支持多个客户端同时进行笔记记录

- 时限: 2wd4~3wd3
- 发布: 发布到各自仓库的 _src/om2py3w/3wex0/ 目录中
- 指标:
    - 包含软件使用说明书: README.md  
    - 能令其它学员根据说明书,运行系统,完成所有功能
- 备选的:
    - 如果有余力!-)
    - 请尝试思考,是否能保存笔记的客户端来源?
    - 并在合适的情景中输出?
    - 进一步的,能根据客户端不同,要求输出不同客户端提交的笔记嘛?

把芝麻星提到的知识点过一遍

socker 是计算机用于通信的接口,用于client 跟server 建立一个socker接口进行数据传输

  • C/S 架构系统

client 跟server 的结构模式,利用两端的环境进行任务分配

  • 什么是 DUP 协议

全称User Datagram Protocol ,把网络的数据压缩成数据的形式,提供信息的传输服务。


系统:mac 10.10.5
Pythone版本:Python 2.7.10

试着把帮助文档的两个例子运行下,只是起到对接作用,并没有传输数据的功能,需要一个能接收数据,一个能传输数据的参数。

把例子用到参数功能了解下

  • socket.bind 把socket绑定到指定的端口跟地址
  • socket.listen 监听链接数量
  • socket.accept 允许链接
  • socket.connect 链接服务器sokcet
  • socket.sendall 传输数据跟服务器socket
  • socket.recv 接收socket数据

帮助文档找到 sendto 用于把数据传送到服务端的socker,再用recv参数接受socket传送过来的数据,先从修改例子入手。

server端

import socket

HOST = 'localhost'
PORT = 50007

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print 'connecting.......'
s.bind((HOST, PORT))

while 1:
    data, addr = s.recvfrom(1024)#关键参数recvfrom,接收socket传过来的数据
    print data
s.close()

client端

import socket

HOST = 'localhost'
PORT = '50007'
w = raw_input('>>>>')
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(w, ('localhost', 50007)) #关键参数sendto,数据传到服务端socket。

开始服务端使用的是recv参数报错,查了下改用 socket.recvfrom 参数试试,用于接受来源地址socker数据

    data, addr = s.recv(1024)
ValueError: too many values to unpack

各种尝试,数据是能从client端传送到服务端了,但每次只能传输一次,就断线了,与目标功能还要很大的差距,还需解决

  1. 如何循环输入
  2. 如何服务端本地保存一份
  3. 如何把1w作业结合进来

加入while 参数实现循环,客户利用s.sendto 传输数据给服务端,用s.recvfrom来接受读取服务端传回来的数据,而服务端再通过s.recvfrom来接受客户端传回来的命令,用s.sendto来把输出传送给客户端。

服务端

while True: #加入while 起到循环作用

    data, addr = s.recvfrom(4097) #接受客户端传送的命令

    if data in 'q': 
        pass
    elif data in 'r':
        f = open('mydiary.txt', 'r') #当客户端传回r,调用阅读本地的mydiry.txt文档
        txt = f.read()
        s.sendto(txt, addr) #并把读取本地文档数据传送给client端
    elif data not in 'r' or 'q':  #如果客户端传来非r or q ,data写入本地文档
        w = open('mydiary.txt', 'a+') 
        w.write("\n" +  data)
        w.close
        print data
    elif not data:

客户端

while True: #加入while 起到循环作用

while True:
    data = raw_input('>>>') #把输入的数据定义成data 

    if data in 'r':
        s.sendto(data, host_port)
        txt, server = s.recvfrom(4096)#读取服务端的mydiary.txt文档
        print txt
    elif data in 'q':
        print 'bye'
        break
    else:
        s.sendto(data, host_port)

s.close()

20151105优化下代码,跟一些细节

添加 upper() 输入命令不区分大小写,
添加time

  • 服务端
    while True:
        data, addr = s.recvfrom(4097)
        print "客户端IP来源 %s, %s" %addr

    if data.upper() in ['R', 'READ']:
        f = open('mydiary.txt', 'r')
        txt = f.read()
        print '---读取历史日记---'
        s.sendto(txt, addr)
    elif data not in '':
        w = open('mydiary.txt', 'a+')
        w.write("\n" + data)
        w.close
        print  data
    elif not data:
        break
  • 客户端
     while True:
        t = time.strftime('%Y-%M-%D')
        data = raw_input(t + '>>> ')

    if data.upper() in ['R', 'READ']:
        s.sendto(data, host_port)
        txt, server = s.recvfrom(4096)
        print txt
    elif data.upper() in ['H', 'HLEP', '?']:
        print '''
         + r/R/read/READ - 读取历史日记
         + q/Q/exit/EXIT/quit/QUIT - 退出
         '''
    elif data.upper() in ['Q', 'EXIT', 'QUIT']:
        print '退出'
        break
    else:
        s.sendto(data, host_port)

更新20151104
更新20151106 代码