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设计】。

相关文章

Python实现小数转化为百分数的格式化输出方法示例

本文实例讲述了Python实现小数转化为百分数的格式化输出方法。分享给大家供大家参考,具体如下: 比如将 0.1234 转化为 12.34% 的形式: rate = .1234 pr...

Python Pandas分组聚合的实现方法

Pycharm 鼠标移动到函数上,CTRL+Q可以快速查看文档,CTR+P可以看基本的参数。 apply(),applymap()和map() apply()和applymap()是Da...

Python的Flask框架中使用Flask-SQLAlchemy管理数据库的教程

Python的Flask框架中使用Flask-SQLAlchemy管理数据库的教程

使用Flask-SQLAlchemy管理数据库 Flask-SQLAlchemy是一个Flask扩展,它简化了在Flask应用程序中对SQLAlchemy的使用。SQLAlchemy是一...

python增加图像对比度的方法

本代码实现的是,在旋转10度的基础上,再进行增加对比度的操作。 1 代码: 代码注释中的代码都是可以运行的.  但是不怎么靠谱,因为文件名被逐个编辑,有可能与原标签不对应,,更...

Python如何读取文件中图片格式

这篇文章主要介绍了Python如何读取文件中图片格式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 正常情况下,图片命名的后缀和图片的...