Python实现的服务器示例小结【单进程、多进程、多线程、非阻塞式】


Posted in Python onMay 23, 2019

本文实例讲述了Python实现的服务器。分享给大家供大家参考,具体如下:

python - 单进程服务器

#coding=utf-8
from socket import *
#创建套接字
serSocket = socket(AF_INET, SOCK_STREAM)
#重复使用绑定信息
serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
localAddr = ('', 7788)
#绑定端口ip
serSocket.bind(localAddr)
#监听
serSocket.listen(5)
while True:
  print('---主进程,等待新客户端的到来---')
  newSocket,destAddr = serSocket.accept()
  print('---主进程,接下来负责数据处理[%s]---'%str(destAddr))
  try:
    while True:
      recvData = newSocket.recv(1024)
      if len(recvData)>0:
        print('recv[%s]:%s'%(str(destAddr),recvData))
      else:
        print('[%s]客户端已经关闭')
        break
  finally:
    newSocket.close()
serSocket.close()

总结

同一时刻只能为一个客户进行服务,不能同时为多个客户服务。
当服务器为一个客户端服务时,另外的客户端发起了connect,只要服务器listen的队列有空闲的位置,就会为这个新客户端进行连接,并且客户端可以发送数据,但当服务器为这个新客户端服务时,可能一次性把所有数据接收完毕当recv接收数据时,返回值为空,即没有返回数据,那么意味着客户端已经调用了close关闭了;因此服务器通过判断recv接收数据是否为空 来判断客户端是否已经下线。

python - 多进程服务器

#coding=utf-8
from socket import *
from multiprocessing import *
from time import sleep
#处理客户端的请求并为其服务
def dealWithClient(newSocket,destAddr):
  try:
    while True:
      recvData = newSocket.recv(1024)
      if len(recvData) > 0:
        print('recv[%s]:%s' % (str(destAddr), recvData))
      else:
        print('[%s]客户端已经关闭')
        break
  finally:
    newSocket.close()
def main():
  #创建套接字
  serSocket = socket(AF_INET, SOCK_STREAM)
  #重复使用绑定信息
  serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
  localAddr = ('', 7788)
  #绑定端口ip
  serSocket.bind(localAddr)
  #监听
  serSocket.listen(5)
  try:
    while True:
      print('---主进程,等待新客户端的到来---')
      newSocket,destAddr = serSocket.accept()
      print('---主进程,接下来负责数据处理[%s]---'%str(destAddr))
      client = Process(target=dealWithClient, args=(newSocket, destAddr))
      client.start()
      # 因为已经向子进程中copy了一份(引用),并且父进程中这个套接字也没有用处了
      # 所以关闭
      newSocket.close()
  finally:
    # 当为所有的客户端服务完之后再进行关闭,表示不再接收新的客户端的链接
    serSocket.close()
if __name__ == '__main__':
  main()

总结

通过为每个客户端创建一个进程的方式,能够同时为多个客户端进行服
务当客户端不是特别多的时候,这种方式还行,如果有成百上千个,就不
可取了,因为每次创建进程的过程需要消耗较多的资源。

python - 多线程服务器

#coding=utf-8
from socket import *
from threading import Thread
from time import sleep
# 处理客户端的请求并执行事情
def dealWithClient(newSocket,destAddr):
  while True:
    recvData = newSocket.recv(1024)
    if len(recvData)>0:
      print('recv[%s]:%s'%(str(destAddr), recvData))
    else:
      print('[%s]客户端已经关闭'%str(destAddr))
      break
  newSocket.close()
def main():
  serSocket = socket(AF_INET, SOCK_STREAM)
  serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR , 1)
  localAddr = ('', 7788)
  serSocket.bind(localAddr)
  serSocket.listen(5)
  try:
    while True:
      print('-----主进程,,等待新客户端的到来------')
      newSocket,destAddr = serSocket.accept()
      print('-----主进程,,接下来创建一个新的进程负责数据处理[%s]----'%str(destAddr))
      client = Thread(target=dealWithClient, args=(newSocket,destAddr))
      client.start()
      #因为线程中共享这个套接字,如果关闭了会导致这个套接字不可用,
      #但是此时在线程中这个套接字可能还在收数据,因此不能关闭
      #newSocket.close()
  finally:
    # 当为所有的客户端服务完之后再进行关闭,表示不再接收新的客户端的链接
    serSocket.close()
if __name__ == '__main__':
  main()

单进程服务器-非堵塞模式

服务器:

#coding=utf-8
from socket import *
import time
# 用来存储所有的新链接的socket
g_socketList = []
def main():
  serSocket = socket(AF_INET, SOCK_STREAM)
  serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR , 1)
  localAddr = ('', 7788)
  serSocket.bind(localAddr)
  #可以适当修改listen中的值来看看不同的现象
  serSocket.listen(1000)
  #将套接字设置为?堵塞
  #设置为?堵塞后,如果accept时,恰巧没有客户端connect,那么accept会
  #产生一个异常,所以需要try来进行处理
  serSocket.setblocking(False)
  while True:
    #?来测试
    #time.sleep(0.5)
    try:
      newClientInfo = serSocket.accept()
    except Exception as result:
      pass
    else:
      print("一个新的客户端到来:%s"%str(newClientInfo))
      newClientInfo[0].setblocking(False)
      g_socketList.append(newClientInfo)
  # 用来存储需要删除的客户端信息
  needDelClientInfoList = []
  for clientSocket,clientAddr in g_socketList:
    try:
      recvData = clientSocket.recv(1024)
      if len(recvData)>0:
        print('recv[%s]:%s'%(str(clientAddr), recvData))
      else:
        print('[%s]客户端已经关闭'%str(clientAddr))
        clientSocket.close()
        g_needDelClientInfoList.append((clientSocket,clientAddr))
    except Exception as result:
      pass
  for needDelClientInfo in needDelClientInfoList:
    g_socketList.remove(needDelClientInfo)
if __name__ == '__main__':
  main()

客户端:

#coding=utf-8
from socket import *
import random
import time
serverIp = input("请输入服务器的ip:")
connNum = input("请输入要链接服务器的次数(例如1000):")
g_socketList = []
for i in range(int(connNum)):
  s = socket(AF_INET, SOCK_STREAM)
  s.connect((serverIp, 7788))
  g_socketList.append(s)
  print(i)
while True:
  for s in g_socketList:
    s.send(str(random.randint(0,100)))
  # 用来测试
  #time.sleep(1)

更多关于Python相关内容可查看本站专题:《Python Socket编程技巧总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
python函数返回多个值的示例方法
Dec 04 Python
利用Python绘制数据的瀑布图的教程
Apr 07 Python
用Python将动态GIF图片倒放播放的方法
Nov 02 Python
详解pyppeteer(python版puppeteer)基本使用
Jun 12 Python
浅谈Python中函数的定义及其调用方法
Jul 19 Python
基于python实现学生信息管理系统
Nov 22 Python
python-web根据元素属性进行定位的方法
Dec 13 Python
windows下Pycharm安装opencv的多种方法
Mar 05 Python
解决pycharm debug时界面下方不出现step等按钮及变量值的问题
Jun 09 Python
详解Python3.8+PyQt5+pyqt5-tools+Pycharm配置详细教程
Nov 02 Python
mac系统下安装pycharm、永久激活、中文汉化详细教程
Nov 24 Python
Python3爬虫RedisDump的安装步骤
Feb 20 Python
Python3.8中使用f-strings调试
May 22 #Python
总结Python图形用户界面和游戏开发知识点
May 22 #Python
Python闭包和装饰器用法实例详解
May 22 #Python
Python进程间通信Queue消息队列用法分析
May 22 #Python
将python文件打包成EXE应用程序的方法
May 22 #Python
Python多线程threading模块用法实例分析
May 22 #Python
Python3之手动创建迭代器的实例代码
May 22 #Python
You might like
php 分页原理详解
2009/08/21 PHP
php求正负数数组中连续元素最大值示例
2014/04/11 PHP
javascript function、指针及内置对象
2009/02/19 Javascript
js类型转换与引用类型详解(Boolean_Number_String)
2014/03/07 Javascript
js调试系列 初识控制台
2014/06/18 Javascript
JQuery遍历DOM节点的方法
2015/06/11 Javascript
AngularJS 让人爱不释手的八种功能
2016/03/23 Javascript
浅谈jquery采用attr修改form表单enctype不起作用的问题
2016/11/25 Javascript
基于vue.js实现图片轮播效果
2016/12/01 Javascript
node.js中express中间件body-parser的介绍与用法详解
2017/05/23 Javascript
基于js中的存储键值对以及注意事项介绍
2018/03/30 Javascript
使用React代码动态生成栅格布局的方法
2020/05/24 Javascript
vue props 一次传多个值实例
2020/07/22 Javascript
[49:21]TNC vs VG 2019DOTA2国际邀请赛淘汰赛 胜者组赛BO3 第三场 8.20.mp4
2019/08/22 DOTA
Python编程中的文件操作攻略
2015/10/16 Python
django项目运行因中文而乱码报错的几种情况解决
2017/11/07 Python
python远程连接服务器MySQL数据库
2018/07/02 Python
20行python代码的入门级小游戏的详解
2019/05/05 Python
pandas 数据索引与选取的实现方法
2019/06/21 Python
python3.4中清屏的处理方法
2020/07/06 Python
澳大利亚电子产品购物网站:Dick Smith
2017/02/02 全球购物
英国在线药房和在线药剂师:Chemist 4 U
2020/01/05 全球购物
毕业生优秀推荐信
2013/11/26 职场文书
自荐信格式
2013/12/01 职场文书
小学生红领巾广播稿
2014/01/21 职场文书
医学求职信
2014/05/28 职场文书
小学生田径运动会广播稿
2014/09/11 职场文书
合伙经营协议书范本
2014/09/13 职场文书
党员“四风”问题批评与自我批评思想汇报
2014/10/06 职场文书
鲁迅故居导游词
2015/02/05 职场文书
绵山导游词
2015/02/05 职场文书
2015初一年级组工作总结
2015/07/24 职场文书
2016党员学习作风建设心得体会
2016/01/21 职场文书
PC版《死亡搁浅导剪版》现已发售 展开全新的探险
2022/04/03 其他游戏
Mysql调整优化之四种分区方式以及组合分区
2022/04/13 MySQL
SpringBoot项目部署到阿里云服务器的实现步骤
2022/06/28 Java/Android