python cs架构实现简单文件传输

yipeiwu_com5年前Python基础

本文为大家分享了python cs架构实现简单文件的传输代码,供大家参考,具体内容如下

要实现简单文件的传输我们必须考虑这些问题:

1.什么是c/s架构?

顾名思义,就是客户端端/服务器架构。不同的人可能回答不一,但是有一点是相同的:服务器是一个软件或硬件,用于向一个或多个客户端提供所需要的服务,服务器存在的唯一目的就是等待客户的请求,给这些客户服务,然后等待其他的请求。

2.客户端与服务端如何通信?

其实说白了就是互联网中两个主机该如何通信,首先我们用ip地址可以标示一台主机,这样就可以通信了么?当然也不行,我们还得标示主机中的进程,当然协议也是不可或缺的,是udp报文协议还是tcp数据流协议,这的看你个人的需求。用套介子来作为一个标示符,唯一标识网络进程。

想明白这两个问题我觉得这个问题有三分之一已经解决了,接下来呢我选择tcp协议来传输。

服务端:

        采用socket()函数 定义socket描述字

        bind()函数来把地址族中一个特定地址赋给socket,简单来说就是把一个ipv4/ipv6地址+端口号组合赋给socket

        listen()函数把socket变成被动类型的,等待客户连接请求。

        当客户端发来消息时用accept()函数来接受请求,同时给服务端返回客户端的socket描述字,接下来服务端以接收到的描述字来向客户端发送信息以及接受信息。

        我们这个程序是实现文件传输,我的想法是类似于ftp程序接受客户上传下载文件的需求。服务端启动后监听端口(我用的9500)等待客户连接。客户端三次握手建立连接后,客户输入命令来向客户端发起请求,输入‘ls'命令可以查看服务端可下载的文件,输入‘put   文件名',‘get  文件名'可以上传下载文件。上传文件时客户端打开本地文件以二进制方式读取文件内容并同时调用send()函数发送文件内容,服务端以写方式打开文件并将客户端上传内容写入文件,实现文件的上传。下载文件与此类似,客户端上传送‘get  文件名'命令同时以写方式打开文件 ,服务端收到命令以读方式打开文件,并发送给服务端。

tcp三次握手建立连接:

当客户端调用connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函 数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。

tcp四次挥手断开连接:

某个应用进程首先调用close主动关闭连接,这时TCP发送一个FIN M;另一端接收到FIN M之后,执行被动关闭,对这个FIN进行确认。它的接收也作为文件结束符传递给应用进程,因为FIN的接收意味着应用进程在相应的连接上再也接收不到额外数据;一段时间之后,接收到文件结束符的应用进程调用close关闭它的socket。这导致它的TCP也发送一个FIN N;接收到这个FIN的源发送端TCP对它进行确认。

服务端代码:

#!/usr/bin/env python
from socket import *
import time
import sys
import os
 
HOST = 'localhost'
PORT = 9500
BUFIZ = 1024
ADDR = (HOST,PORT)
 
def recvfile(filename):
  print 'starting receive file...'
  f = open(filename,'wb')
  cliSockfd.send('no problem')
  while True:
    data = cliSockfd.recv(4096)
    if data == 'EOF':
      print 'recved file success!'
      break
    f.write(data)
  f.close()
 
def sendfile(filename):
  print 'starting send file...'
  cliSockfd.send('no problem')
  f = open(filename,'rb')
  while True:
    data = f.read(4096)
    if not data:
      break
    cliSockfd.send(data)
  f.close()
  time.sleep(1)
  cliSockfd.send('EOF')
  print 'send file success!'
def handle1(act,filename):
  if act == 'put':
    print 'recving msg!'
    recvfile(filename)
  elif act == 'get':
    print 'sending msg!'
    sendfile(filename)
  else:
    print 'error!'
 
def handle2(act):
  if act == 'ls':
    path = sys.path[0]
    every_file = os.listdir(path)
    for filename in every_file: 
      cliSockfd.send(filename + ' ')
    time.sleep(1)
    cliSockfd.send('EOF')
    print 'all filename has send to client success!'
  else:
    print 'command error'
 
sockfd = socket(AF_INET,SOCK_STREAM)
sockfd.bind(ADDR)
sockfd.listen(5)
while True:
  print 'waiting for connection...'
  cliSockfd,addr = sockfd.accept()
  print '...connected from:',addr
  
  while True:
    msg = cliSockfd.recv(4096)
    if msg == 'close':
      print 'client closed'
      break
    info = msg.split()
    if len(info) == 2:
      handle1(*info)
    elif len(info) == 1:
      handle2(*info)
    else:
      print 'command error!'
      break

客户端代码:

#!/usr/bin/env python
import sys
import socket
import time
HOST = 'localhost'
PORT = 9500
BUFSIZ = 1024
ADDR = (HOST,PORT)
 
cliSockfd = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 
def recvfile(filename):
  f = open(filename,'wb')
  while True:
    msg = cliSockfd.recv(4096)
    if msg == 'EOF':
      print 'recv file success!'
      break
    f.write(msg)
  f.close
def sendfile(filename):
  f = open(filename,'rb')
  while True:
    msg = f.read(4096)
    if not msg:
       break
    cliSockfd.sendall(msg)
  f.close()
  time.sleep(1)
  cliSockfd.sendall('EOF')
  print 'send file success'
def confirm(cliSockfd,client_command):
  cliSockfd.send(client_command)
  msg = cliSockfd.recv(4096)
  if msg == 'no problem':
    return True
 
def handle1(act,filename):
  if act == 'put':
    if confirm(cliSockfd,client_command):
      sendfile(filename)
    else:
      print 'server error1!'
  elif act == 'get':
    if confirm(cliSockfd,client_command):
      recvfile(filename)
    else:
      print 'server error2!'
  else:
    print 'command error!'
def handle2(act):
  if act == 'ls':
    cliSockfd.send('ls')
    while True:
      msg = cliSockfd.recv(1024)
      if msg == 'EOF':
        break
      print msg
  else:
    print 'command error'
 
try:
  cliSockfd.connect(ADDR)
  print 'connect to ',ADDR
  while True:
    client_command = raw_input('>>>')
    if not client_command:
      continue
    msg = client_command.split()
    if len(msg) == 2:
      handle1(*msg)
    elif len(msg) == 1 and msg != ['close']:
      handle2(*msg)
    elif len(msg) == 1 and msg == ['close']:
      cliSockfd.send('close')
      break
    else:
      print 'command error'
except socket.error,e:
  print 'error:',e
finally:
  cliSockfd.close()

运行截图:

服务端:

客户端:

欢迎各位大牛,多提宝贵意见。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持【听图阁-专注于Python设计】。

相关文章

Android 兼容性问题:java.lang.UnsupportedOperationException解决办法

Android 兼容性问题:java.lang.UnsupportedOperationException解决办法

在前几天的开发中,遇到这么个非常奇葩的异常,有些手机可以运行,有些手机却直接就崩了,今天就把这异常整理下。 首先还是贴上其异常信息 E/AndroidRuntime: FATAL E...

python3使用PyMysql连接mysql数据库实例

python语言的3.x完全不向前兼容,导致我们在python2.x中可以正常使用的库,到了python3就用不了了.比如说mysqldb 目前MySQLdb并不支持python3.x...

Python异常处理操作实例详解

本文实例讲述了Python异常处理操作。分享给大家供大家参考,具体如下: 常见异常 在python中不同的异常可以用不同的类型(python中统一了类与类型,类型即类)去标识,不同的类对...

解决python 输出是省略号的问题

这个问题非常非常重要,搞了一晚上都没解决好,但是真的很简单很简单, 如果你也 是用的numpy array, 如果你也想得到输出矩阵的全部内容,而不是省略形式, [[ 0.10284...

人机交互程序 python实现人机对话

自己随便写了一个人机交互的程序。不存在任何智能,只是可以识别姓名,可以记录对话内容,并保存等到下一次交互时加载。 (推荐面向对象版本) # hello.py # 这是老早写的。不过...