作业:开发一个支持多用户在线的FTP程序

要求:

  1. 用户加密认证
  2. 允许同时多用户登录
  3. 每个用户有自己的家目录 ,且只能访问自己的家目录
  4. 对用户进行磁盘配额,每个用户的可用空间不同
  5. 允许用户在ftp server上随意切换目录
  6. 允许用户查看当前目录下文件
  7. 允许上传和下载文件,保证文件一致性
  8. 文件传输过程中显示进度条
  9. 附加功能:支持文件的断点续传(仅下载)

程序

1、最最重要的readme:

  1. ### 作者介绍:
  2. * authorlzl
  3. ### 博客地址:
  4. * http://www.cnblogs.com/lianzhilei/p/5813986.html
  5.  
  6. ### 功能实现
  7. 作业:开发一个支持多用户在线的FTP程序
  8. 要求:
  9. 用户加密认证
  10. 允许同时多用户登录
  11. 每个用户有自己的家目录 ,且只能访问自己的家目录
  12. 对用户进行磁盘配额,每个用户的可用空间不同
  13. 允许用户在ftp server上随意切换目录
  14. 允许用户查看当前目录下文件
  15. 允许上传和下载文件,保证文件一致性
  16. 文件传输过程中显示进度条
  17. 附加功能:支持文件的断点续传
  18.  
  19. ### 目录结构:
  20. FTP

  21. ├── ftpclient #客户端程序
  22. ├── __init__.py
  23. └── ftpclient.py #客户端主程序
  24. └── ftpserver #服务端程序
  25. ├── README.txt
  26. ├── ftpserver.py #服务端入口程序
  27. ├── conf #配置文件目录
  28. ├── __init__.py
  29. └── setting.py
  30. ├── modules #程序核心目录
  31. ├── __init__.py
  32. ├── auth_user.py #用户认证模块
  33. └── sokect_server.py #sokectserver模块
  34. ├── database #用户数据库
  35. ├── alex.db
  36. ├── lzl.db
  37. └── eric.db
  38. ├── home #用户宿主目录
  39. ├── alex
  40. ├── lzl
  41. └── eric
  42. └── log
  43. ├── __init__.py
  44. └── log #待扩展....
  45.  
  46. ### 功能实现
  47.  
  48. 1conf目录下settings.py模块记录可操作用户信息,根据用户信息生成用户字典和宿主目录,已经生成的不再新建
  49. 2、每个用户的宿主目录磁盘空间配额默认为10M,可在settings.py模块里进行修改
  50. 3、程序运行在windows系统上,程序要求全部实现,下面是具体命令操作
  51. 4、切换目录:cd .. 返回上一级目录 cd dirname 进入dirname
  52. 用户登录后默认进入宿主目录,只可在宿主目录下随意切换
  53.  
  54. 5、创建目录:mkdir dirname
  55. 在当前目录下创建目录,如果目录存在则报错,不存在创建
  56.  
  57. 6、查看当前路径: pwd
  58.  
  59. 7、查看当前路径下的文件名和目录名: dir
  60.  
  61. 8、下载文件(可续传):get filename
  62. ①、服务端当前目录存在此文件,客户端不存在此文件,直接下载
  63. ②、服务端当前目录存在此文件,客户端存在此文件名,之前下载中断,文件可续传,进行续传
  64. ③、服务端当前目录存在此文件,客户端存在此文件名,大小与服务端一致,不下载
  65.  
  66. 9、上传文件:put filename
  67. 判断宿主目录磁盘空间是否够用,可以,上传文件;否则,报错
  68.  
  69. ### 状态码
  70.  
  71. 400 用户认证失败
  72. 401 命令不正确
  73. 402 文件不存在
  74. 403 创建文件已经存在
  75. 404 磁盘空间不够
  76. 405 不续传
  77.  
  78. 200 用户认证成功
  79. 201 命令可以执行
  80. 202 磁盘空间够用
  81. 203 文件具有一致性
  82. 205 续传
  83.  
  84. 000 系统交互码

Readme

2、程序目录结构:

3、ftp客户端

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. #-Author-Lian
  4.  
  5. import socket
  6. import os,sys
  7. import hashlib
  8.  
  9. class Myclient():
  10. '''ftp客户端'''
  11. def __init__(self,ip_port):
  12. self.ip_port = ip_port
  13.  
  14. def connect(self):
  15. '''连接服务器'''
  16. self.client = socket.socket()
  17. self.client.connect(self.ip_port)
  18.  
  19. def start(self):
  20. '''程序开始'''
  21. self.connect()
  22. while True:
  23. username = input("输入用户名:").strip()
  24. password = input("输入密码:").strip()
  25. login_info = ("%s:%s" %(username, password))
  26. self.client.sendall(login_info.encode()) #发送用户密码信息
  27. status_code = self.client.recv(1024).decode() #返回状态码
  28. if status_code == "":
  29. print("[%s]用户密码认证错误"%status_code)
  30. continue
  31. else:print("[%s]用户密码认证成功"%status_code)
  32. self.interactive()
  33.  
  34. def interactive(self):
  35. '''开始交互'''
  36. while True:
  37. command = input("->>").strip()
  38. if not command:continue
  39. #if command == "exit":break
  40. command_str = command.split()[0]
  41. if hasattr(self,command_str): # 执行命令
  42. func = getattr(self,command_str)
  43. func(command)
  44. else:print("[%s]命令不存在"%401)
  45.  
  46. def get(self,command):
  47. '''下载文件'''
  48. self.client.sendall(command.encode()) #发送要执行的命令
  49. status_code = self.client.recv(1024).decode()
  50. if status_code == "": #命令可执行
  51. filename = command.split()[1]
  52.  
  53. # 文件名存在,判断是否续传
  54. if os.path.isfile(filename):
  55. revice_size = os.stat(filename).st_size #文件已接收大小
  56. self.client.sendall("".encode())
  57. response = self.client.recv(1024)
  58. self.client.sendall(str(revice_size).encode()) #发送已接收文件大小
  59. status_code = self.client.recv(1024).decode()
  60.  
  61. # 文件大小不一致,续传
  62. if status_code == "":
  63. print("继续上次上传位置进行续传")
  64. self.client.sendall("".encode())
  65.  
  66. # 文件大小一致,不续传,不下载
  67. elif status_code == "":
  68. print("文件已经存在,大小一致")
  69. return
  70.  
  71. # 文件不存在
  72. else:
  73. self.client.sendall("".encode())
  74. revice_size = 0
  75.  
  76. file_size = self.client.recv(1024).decode() #文件大小
  77. file_size = int(file_size)
  78. self.client.sendall("".encode())
  79.  
  80. with open(filename,"ab") as file: #开始接收
  81. #file_size 为文件总大小
  82. file_size +=revice_size
  83. m = hashlib.md5()
  84. while revice_size < file_size:
  85. minus_size = file_size - revice_size
  86. if minus_size > 1024:
  87. size = 1024
  88. else:
  89. size = minus_size
  90. data = self.client.recv(size)
  91. revice_size += len(data)
  92. file.write(data)
  93. m.update(data)
  94. self.__progress(revice_size,file_size,"下载中") #进度条
  95. new_file_md5 = m.hexdigest() #生成新文件的md5值
  96. server_file_md5 = self.client.recv(1024).decode()
  97. if new_file_md5 == server_file_md5: #md5值一致
  98. print("\n文件具有一致性")
  99. else:print("[%s] Error!"%(status_code))
  100.  
  101. def put(self,command):
  102. '''上传文件'''
  103. if len(command.split()) > 1:
  104. filename = command.split()[1]
  105. #file_path = self.current_path + r"\%s"%filename
  106. if os.path.isfile(filename): #文件是否存在
  107. self.client.sendall(command.encode()) #发送要执行的命令
  108. response = self.client.recv(1024) #收到ack确认
  109.  
  110. file_size = os.stat(filename).st_size # 文件大小
  111. self.client.sendall(str(file_size).encode()) # 发送文件大小
  112. status_code = self.client.recv(1024).decode() # 等待响应,返回状态码
  113. if status_code == "":
  114. with open(filename,"rb") as file:
  115. m = hashlib.md5()
  116. for line in file:
  117. m.update(line)
  118. send_size = file.tell()
  119. self.client.sendall(line)
  120. self.__progress(send_size, file_size, "上传中") # 进度条
  121. self.client.sendall(m.hexdigest().encode()) #发送文件md5值
  122. status_code = self.client.recv(1024).decode() #返回状态码
  123. if status_code == "":
  124. print("\n文件具有一致性")
  125. else:print("[%s] Error!"%(status_code))
  126. else:
  127. print("[402] Error")
  128. else: print("[401] Error")
  129.  
  130. def dir(self,command):
  131. '''查看当前目录下的文件'''
  132. self.__universal_method_data(command)
  133. pass
  134.  
  135. def pwd(self,command):
  136. '''查看当前用户路径'''
  137. self.__universal_method_data(command)
  138. pass
  139.  
  140. def mkdir(self,command):
  141. '''创建目录'''
  142. self.__universal_method_none(command)
  143. pass
  144.  
  145. def cd(self,command):
  146. '''切换目录'''
  147. self.__universal_method_none(command)
  148. pass
  149.  
  150. def __progress(self, trans_size, file_size,mode):
  151. '''
  152. 显示进度条
  153. trans_size: 已经传输的数据大小
  154. file_size: 文件的总大小
  155. mode: 模式
  156. '''
  157. bar_length = 100 #进度条长度
  158. percent = float(trans_size) / float(file_size)
  159. hashes = '=' * int(percent * bar_length) #进度条显示的数量长度百分比
  160. spaces = ' ' * (bar_length - len(hashes)) #定义空格的数量=总长度-显示长度
  161. sys.stdout.write(
  162. "\r%s:%.2fM/%.2fM %d%% [%s]"%(mode,trans_size/1048576,file_size/1048576,percent*100,hashes+spaces))
  163. sys.stdout.flush()
  164.  
  165. def __universal_method_none(self,command):
  166. '''通用方法,无data输出'''
  167. self.client.sendall(command.encode()) # 发送要执行的命令
  168. status_code = self.client.recv(1024).decode()
  169. if status_code == "": # 命令可执行
  170. self.client.sendall("".encode()) # 系统交互
  171. else:
  172. print("[%s] Error!" % (status_code))
  173.  
  174. def __universal_method_data(self,command):
  175. '''通用方法,有data输出'''
  176. self.client.sendall(command.encode()) #发送要执行的命令
  177. status_code = self.client.recv(1024).decode()
  178. if status_code == "": #命令可执行
  179. self.client.sendall("".encode()) #系统交互
  180. data = self.client.recv(1024).decode()
  181. print(data)
  182. else:print("[%s] Error!" % (status_code))
  183.  
  184. if __name__ == "__main__":
  185. ip_port =("127.0.0.1",9999) #服务端ip、端口
  186. client = Myclient(ip_port) #创建客户端实例
  187. client.start() #开始连接

ftpclient.py

4、ftp服务端

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. #-Author-Lian
  4.  
  5. import os,hashlib
  6. import json
  7. from conf import settings
  8. from modules import auth_user
  9. from modules import sokect_server
  10.  
  11. def create_db():
  12. '''创建用户数据库文件'''
  13. user_database={}
  14. encryption = auth_user.User_operation()
  15. limitsize = settings.LIMIT_SIZE
  16. for k,v in settings.USERS_PWD.items():
  17. username = k
  18. password = encryption.hash(v)
  19. user_db_path = settings.DATABASE + r"\%s.db"%username
  20. user_home_path = settings.HOME_PATH + r"\%s"%username
  21. user_database["username"] = username
  22. user_database["password"] = password
  23. user_database["limitsize"] = limitsize
  24. user_database["homepath"] = user_home_path
  25. if not os.path.isfile(user_db_path):
  26. with open(user_db_path,"w") as file:
  27. file.write(json.dumps(user_database))
  28.  
  29. def create_dir():
  30. '''创建用户属主目录'''
  31. for username in settings.USERS_PWD:
  32. user_home_path = settings.HOME_PATH + r"\%s" %username
  33. if not os.path.isdir(user_home_path):
  34. os.popen("mkdir %s" %user_home_path)
  35.  
  36. if __name__ == "__main__":
  37. '''初始化系统数据并启动程序'''
  38. create_db() #创建数据库
  39. create_dir() #创建属主目录
  40. #启动ftp服务
  41. server = sokect_server.socketserver.ThreadingTCPServer(settings.IP_PORT, sokect_server.Myserver)
  42. server.serve_forever()

ftpserver.py

5、conf配置文件

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. #-Author-Lian
  4.  
  5. import os,sys
  6.  
  7. #程序主目录文件
  8. BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  9. #添加环境变量
  10. sys.path.insert(0,BASE_DIR)
  11.  
  12. #数据库目录
  13. DATABASE = os.path.join(BASE_DIR,"database")
  14.  
  15. #用户属主目录
  16. HOME_PATH = os.path.join(BASE_DIR,"home")
  17.  
  18. #用户字典
  19. USERS_PWD = {"alex":"","lzl":"","eric":""}
  20.  
  21. #磁盘配额 10M
  22. LIMIT_SIZE = 10240000
  23.  
  24. #ftp服务端口
  25. IP_PORT = ("0.0.0.0",9999)

settings.py

6、database用户数据库(系统初始化自动生成)

  1. {"username": "alex", "password": "e10adc3949ba59abbe56e057f20f883e", "limitsize": 10240000, "homepath": "C:\\Users\\L\\PycharmProjects\\s14\\homework\\Day8\\FTP\\ftpserver\\home\\alex"}

lzl.db

  1. {"username": "eric", "password": "e9510081ac30ffa83f10b68cde1cac07", "limitsize": 10240000, "homepath": "C:\\Users\\L\\PycharmProjects\\s14\\homework\\Day8\\FTP\\ftpserver\\home\\eric"}

eric.db

  1. {"username": "alex", "password": "e10adc3949ba59abbe56e057f20f883e", "limitsize": 10240000, "homepath": "C:\\Users\\L\\PycharmProjects\\s14\\homework\\Day8\\FTP\\ftpserver\\home\\alex"}

alex.db

7、modules模块dd

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. #-Author-Lian
  4.  
  5. import json
  6. import sys,os
  7. import hashlib
  8. from conf import settings
  9.  
  10. class User_operation():
  11. '''对登录信息进行认证,登录成功返回用户名,失败返回None'''
  12. def authentication(self,login_info):
  13. list = login_info.split(":") #对信息进行分割
  14. login_name = list[0]
  15. login_passwd = self.hash(list[1])
  16. DB_FILE = settings.DATABASE + r"\%s.db"%login_name
  17. if os.path.isfile(DB_FILE):
  18. user_database = self.cat_database(DB_FILE) #用户数据库信息
  19. if login_name == user_database["username"]:
  20. if login_passwd == user_database["password"]:
  21. return user_database
  22.  
  23. def cat_database(self,DB_FILE):
  24. #获取数据库信息
  25. with open(DB_FILE,"r") as file:
  26. data = json.loads(file.read())
  27. return data
  28.  
  29. def hash(self,passwd):
  30. '''对密码进行md5加密'''
  31. m = hashlib.md5()
  32. m.update(passwd.encode("utf-8"))
  33. return m.hexdigest()

auth_user.py

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. #-Author-Lian
  4.  
  5. import socketserver
  6. import sys,os
  7. import hashlib
  8. from os.path import join, getsize
  9. from conf import settings
  10. from modules import auth_user
  11.  
  12. class Myserver(socketserver.BaseRequestHandler):
  13. '''ftp服务端'''
  14. def handle(self):
  15. try:
  16. self.conn = self.request
  17. while True:
  18. login_info = self.conn.recv(1024).decode() # 接收客户端发的的账号密码信息
  19. result = self.authenticat(login_info)
  20. status_code = result[0]
  21. self.conn.sendall(status_code.encode())
  22. if status_code == "":
  23. continue
  24. self.user_db = result[1] #当前登录用户信息
  25. self.current_path = self.user_db["homepath"] #用户当前目录
  26. self.home_path = self.user_db["homepath"] #用户宿主目录
  27.  
  28. while True:
  29. command = self.conn.recv(1024).decode()
  30. command_str = command.split()[0]
  31. if hasattr(self,command_str):
  32. func = getattr(self,command_str)
  33. func(command)
  34. else:self.conn.sendall("".encode())
  35. except ConnectionResetError as e:
  36. self.conn.close()
  37. print(e)
  38.  
  39. def authenticat(self,login_info):
  40. '''认证用户'''
  41. auth = auth_user.User_operation() # 创建认证实例
  42. result = auth.authentication(login_info) # 认证用户
  43. if result:return "",result
  44. else:return "",result
  45.  
  46. def get(self,command):
  47. '''下载文件'''
  48. if len(command.split()) > 1:
  49. filename = command.split()[1]
  50. file_path = self.current_path + r"\%s"%filename
  51. if os.path.isfile(file_path): #文件是否存在
  52. self.conn.sendall("".encode()) #命令可执行
  53. file_size = os.stat(file_path).st_size # 文件总大小
  54. status_code = self.conn.recv(1024).decode()
  55.  
  56. # 客户端存在此文件
  57. if status_code == "":
  58. self.conn.sendall("".encode()) #系统交互
  59. has_send_size = self.conn.recv(1024).decode()
  60. has_send_size = int(has_send_size)
  61. # 客户端文件不完整可续传
  62. if has_send_size < file_size:
  63. self.conn.sendall("".encode())
  64. file_size -= has_send_size #续传文件大小
  65. response = self.conn.recv(1024) # 等待响应
  66.  
  67. # 客户端文件完整不可续传、不提供下载
  68. else:
  69. self.conn.sendall("".encode())
  70. return
  71. # 客户端不存在此文件
  72. elif status_code == "":
  73. has_send_size = 0
  74.  
  75. with open(file_path,"rb") as file:
  76. self.conn.sendall(str(file_size).encode()) #发送文件大小
  77. response = self.conn.recv(1024) #等待响应
  78. file.seek(has_send_size)
  79. m = hashlib.md5()
  80. for line in file:
  81. m.update(line)
  82. self.conn.sendall(line)
  83. self.conn.sendall(m.hexdigest().encode()) #发送文件md5值
  84. else:self.conn.sendall("".encode())
  85. else:self.conn.sendall("".encode())
  86.  
  87. def put(self,command):
  88. '''上传文件'''
  89. filename = command.split()[1]
  90. file_path = self.current_path + r"\%s" % filename
  91. self.conn.sendall("".encode()) #发送确认
  92. file_size = self.conn.recv(1024).decode() # 文件大小
  93. file_size = int(file_size)
  94. limit_size = self.user_db["limitsize"] #磁盘额度
  95. used_size = self.__getdirsize(self.home_path) #已用空间大小
  96. if limit_size >= file_size+used_size:
  97. self.conn.sendall("".encode())
  98. with open(file_path, "wb") as file: # 开始接收
  99. revice_size = 0
  100. m = hashlib.md5()
  101. while revice_size < file_size:
  102. minus_size = file_size - revice_size
  103. if minus_size > 1024:
  104. size = 1024
  105. else:
  106. size = minus_size
  107. data = self.conn.recv(size)
  108. revice_size += len(data)
  109. file.write(data)
  110. m.update(data)
  111. new_file_md5 = m.hexdigest() # 生成新文件的md5值
  112. server_file_md5 = self.conn.recv(1024).decode()
  113. if new_file_md5 == server_file_md5: # md5值一致
  114. self.conn.sendall("".encode())
  115. else:self.conn.sendall("".encode())
  116.  
  117. def dir(self,command):
  118. '''查看当前目录下的文件'''
  119. if len(command.split()) == 1:
  120. self.conn.sendall("".encode())
  121. response = self.conn.recv(1024)
  122. send_data = os.popen("dir %s"%self.current_path)
  123. self.conn.sendall(send_data.read().encode())
  124. else:self.conn.sendall("".encode())
  125.  
  126. def pwd(self,command):
  127. '''查看当前用户路径'''
  128. if len(command.split()) == 1:
  129. self.conn.sendall("".encode())
  130. response = self.conn.recv(1024)
  131. send_data = self.current_path
  132. self.conn.sendall(send_data.encode())
  133. else:self.conn.sendall("".encode())
  134.  
  135. def mkdir(self,command):
  136. '''创建目录'''
  137. if len(command.split()) > 1:
  138. dir_name = command.split()[1] #目录名
  139. dir_path = self.current_path + r"\%s"%dir_name #目录路径
  140. if not os.path.isdir(dir_path): #目录不存在
  141. self.conn.sendall("".encode())
  142. response = self.conn.recv(1024)
  143. os.popen("mkdir %s"%dir_path)
  144. else:self.conn.sendall("".encode())
  145. else:self.conn.sendall("".encode())
  146.  
  147. def cd(self,command):
  148. '''切换目录'''
  149. if len(command.split()) > 1:
  150. dir_name = command.split()[1] #目录名
  151. dir_path = self.current_path + r"\%s" %dir_name #目录路径
  152. user_home_path = settings.HOME_PATH + r"\%s"%self.user_db["username"] #宿主目录
  153. if dir_name == ".." and len(self.current_path)>len(user_home_path):
  154. self.conn.sendall("".encode())
  155. response = self.conn.recv(1024)
  156. self.current_path = os.path.dirname(self.current_path) #返回上一级目录
  157. elif os.path.isdir(dir_path) :
  158. self.conn.sendall("".encode())
  159. response = self.conn.recv(1024)
  160. if dir_name != "." and dir_name != "..":
  161. self.current_path += r"\%s"%dir_name #切换目录
  162.  
  163. else:self.conn.sendall("".encode())
  164. else:self.conn.sendall("".encode())
  165.  
  166. def __getdirsize(self,home_path):
  167. '''统计目录空间大小'''
  168. size = 0
  169. for root, dirs, files in os.walk(home_path):
  170. size += sum([getsize(join(root, name)) for name in files])
  171. return size

sokect_server.py

效果图:

下载:

续传:

Python开发【项目】:FTP程序的更多相关文章

  1. 用python开发简单ftp程序

    根据alex老师视频开发的简单ftp程序,只能实现简单的get功能 ftp客户端程序: #!/usr/bin/env python #_*_ coding:utf-8 _*_ import socke ...

  2. Python开发项目:大型模拟战争游戏(外星人入侵)

    外星人入侵 游戏概述: 现在准备用python开始搞一个大型游戏,模拟未来战争,地球人狙击外星人大战(其实就是小蜜蜂游戏2333),玩家控制一个飞船,用子弹歼灭屏幕上空的外星飞船:项目用到了Pygam ...

  3. elipse+pydev+python开发arcgis脚本程序

    环境配置参考:http://www.cnblogs.com/halfacre/archive/2012/07/22/2603848.html 添加arcpy类库.arctoolbox.arcgis-b ...

  4. Python 开发 项目《外星人入侵》

    2019-02-05 本篇心路历程: 本篇是打算记录自己的第一个python项目,也是众人皆知的<外星人入侵项目>,本项目大概500多行.趁着寒假,大概耗时3天吧,把完整代码敲了出来,当然 ...

  5. 〖Android〗从Android Studio转为Eclipse开发项目运行程序闪退的解决方法

    很久没有撸Android App开发了- 最近把一个月前通过反编译.二次修改的Android SSHD项目进行简单修改一下: 突然发现迁移项目时,报了一个错误,同时还出现了闪退情况: - ::): t ...

  6. python开发项目:学生选课系统

    程序要求:1.创建北京.上海两所学校(分析:通过学校类实例化两个学校实例) 2.创建Linux.python.go三个课程,Linux\go在北京开,Linux在上海开(创建Linux.python. ...

  7. 使用Python开发鸿蒙设备程序(0-初体验)

    到目前为止,鸿蒙设备开发的"官方指定语言"还是C语言! 这看起来是一件正常的事,毕竟鸿蒙设备开发还是属于嵌入式开发的范畴,而在嵌入式开发中C语言又是当之无愧的首选,所以,大家也都接 ...

  8. C++ Builder平台使用Indy9开发自动FTP程序01

    Indy9与CB自带的Indy8不同处还是挺多的.首先就是图标变漂亮了,其次很多Method都重写了.它主要是依据Delph里的函数,力求与之相通.不同点在本系列的后续章节中会一一介绍. 在写ftp代 ...

  9. python简单的ftp程序

    服务器端 '''1.读取文件名2.检测文件是否存在3.打开文件4.检测文件大小5.发送文件大小给客户端6.等客户端确认7.开始边读边发数据8.发送md5'''import socket,os,time ...

  10. 2020年python开发微信小程序,公众号,手机购物商城APP

    2020年最新的技术全栈,手机短信注册登陆等运用, 精准定位用户 支付宝支付 以及前后端从0到大神的全部精解 2020年最新的技术全栈,手机短信注册登陆等运用, 精准定位用户 支付宝支付 以及前后端从 ...

随机推荐

  1. idea中用maven打包spring的java项目(非web)

    之前一直用安装的maven打包spring的javaweb项目,用的是mvn assembly:assembly打包,这次打包非web的spring项目,遇到许多问题,特记录一下正确步骤. 1.配置p ...

  2. 2 http协议

    http协议简介: HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于万维网(WWW:World Wide Web )服务器与本地浏览器之间传输超文 ...

  3. 批量上传图片(jQuery-File-Upload使用)

    jQuery-File-Upload jQuery-File-Upload是一个jquery下的ajax文件上传插件,支持批量上传,github地址:https://github.com/blueim ...

  4. Apache Spark 2.2.0 中文文档

    Apache Spark 2.2.0 中文文档 - 快速入门 | ApacheCN Geekhoo 关注 2017.09.20 13:55* 字数 2062 阅读 13评论 0喜欢 1 快速入门 使用 ...

  5. 程序员最值得听的歌曲TOP10

      No.10 一剪梅 费玉清 - 玉笛公子 <一剪梅>是1984年台湾同名电视剧的片头曲,原唱为林禹胜,经典版本由费玉清演唱,后又成为2009年霍建华.吕一主演电视剧<新一剪梅&g ...

  6. Lazarus教程 中文版后续给出

    市面上有介绍Delphi的书籍(近来Delphi的书也是越来越少了),但没有一本系统的介绍Lazarus的书,这本书是网上的仅有的一本Lazarus教程,目前全部是英文,不过我已经着手开始翻译,争取尽 ...

  7. jeakins用户配置

    进入jeakins:系统管理-全局安全设置 如果有多个用户视情况而定进行权限配置

  8. 常用模块(datatime)

    import datetime,time# dt = datetime.datetime.now() # 获取当前时间的时间对象# dt = datetime.date.fromtimestamp(t ...

  9. Lua3

    Lua中的table不是一种简单的数据结构,它可以作为其它数据结构的基础.如数组.记录.线性表.队列和集合等,在Lua中都可以通过table来表示. 1.数组 使用整数来索引table即可在Lua中实 ...

  10. Python网络编程(http协议,IO多路复用、select内核监听)

    前言: 什么是IO? 分为IO设备和IO接口两个部分 如Linux系统,I/O操作可以有多种方式 比如DIO(DirectI/O) AIO(AsynchronousI/O异步I/O) Memory-M ...