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中的闭包
Jul 08 Python
python中requests爬去网页内容出现乱码问题解决方法介绍
Oct 25 Python
Python爬虫包BeautifulSoup学习实例(五)
Jun 17 Python
浅谈pytorch和Numpy的区别以及相互转换方法
Jul 26 Python
pandas 空的dataframe 插入列名的示例
Oct 30 Python
PyTorch的深度学习入门教程之构建神经网络
Jun 27 Python
postman模拟访问具有Session的post请求方法
Jul 15 Python
详解Django 时间与时区设置问题
Jul 23 Python
详解Django将秒转换为xx天xx时xx分
Sep 27 Python
Python 爬取必应壁纸的实例讲解
Feb 24 Python
python实现剪贴板的操作
Jul 01 Python
Python使用pyecharts控件绘制图表
Jun 05 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数字运算验证码的实现代码
2015/07/30 PHP
jquery submit ie6下失效的原因分析及解决方法
2013/11/15 Javascript
按钮接受回车事件的三种实现方法
2014/06/06 Javascript
JS 在指定数组中随机取出N个不重复的数据
2014/06/10 Javascript
谈谈AngularJs中的隐藏和显示
2015/12/09 Javascript
jQuery实现的网格线绘制方法
2016/06/20 Javascript
Angular下H5上传图片的方法(可多张上传)
2017/01/09 Javascript
javascript中json对象json数组json字符串互转及取值方法
2017/04/19 Javascript
基于jQuery的表单填充实例
2017/08/22 jQuery
微信小程序6位或多位验证码密码输入框功能的实现代码
2018/05/29 Javascript
vue axios 简单封装以及思考
2018/10/09 Javascript
webpack4 SplitChunks实现代码分隔详解
2019/05/23 Javascript
jquery 键盘事件 keypress() keydown() keyup()用法总结
2019/10/23 jQuery
Python去掉字符串中空格的方法
2014/03/11 Python
详解在Python程序中自定义异常的方法
2015/10/16 Python
Python实现二叉树的常见遍历操作总结【7种方法】
2019/03/06 Python
Python Excel处理库openpyxl使用详解
2019/05/09 Python
如何基于windows实现python定时爬虫
2020/05/01 Python
解决python cv2.imread 读取中文路径的图片返回为None的问题
2020/06/02 Python
python 监控logcat关键字功能
2020/09/04 Python
Pytorch实现WGAN用于动漫头像生成
2021/03/04 Python
CSS3中的元素过渡属性transition示例详解
2016/11/30 HTML / CSS
html5配合css3实现带提示文字的输入框(摆脱js)
2013/03/08 HTML / CSS
html5教程实现Photoshop渐变色效果
2013/12/04 HTML / CSS
西安当代医院管理研究院笔试题
2015/12/11 面试题
园林毕业生自我鉴定范文
2013/12/29 职场文书
爱国演讲稿400字
2014/05/07 职场文书
工地宣传标语
2014/06/18 职场文书
整改通知书格式
2015/04/22 职场文书
地道战观后感400字
2015/06/04 职场文书
卢旺达饭店观后感
2015/06/05 职场文书
2015年幼师个人工作总结
2015/10/15 职场文书
Python如何导出导入所有依赖包详解
2021/06/08 Python
MySQL8.0升级的踩坑历险记
2021/11/01 MySQL
JavaCV实现照片马赛克效果
2022/01/22 Java/Android
Windows Server 2019 配置远程控制以及管理方法
2022/04/28 Servers