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多进程同步Lock、Semaphore、Event实例
Nov 21 Python
在Python的Django框架中使用通用视图的方法
Jul 21 Python
python django 访问静态文件出现404或500错误
Jan 20 Python
Python 转义字符详细介绍
Mar 21 Python
Python实现连接postgresql数据库的方法分析
Dec 27 Python
Python标准库笔记struct模块的使用
Feb 22 Python
对Python w和w+权限的区别详解
Jan 23 Python
Python3列表内置方法大全及示例代码小结
May 10 Python
pytorch 在网络中添加可训练参数,修改预训练权重文件的方法
Aug 17 Python
python如何使用代码运行助手
Jul 03 Python
python 制作python包,封装成可用模块教程
Jul 13 Python
Python 中random 库的详细使用
Jun 03 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
2014年最新推荐的10款 PHP 开发框架
2014/08/01 PHP
PHP封装的PDO数据库操作类实例
2017/06/21 PHP
利用php + Laravel如何实现部署自动化详解
2017/10/11 PHP
php根据命令行参数生成配置文件详解
2019/03/15 PHP
用Javascript读取中文COOKIE的解决办法
2007/02/15 Javascript
javascript 关于# 和 void的区别分析
2009/10/26 Javascript
js的2种继承方式详解
2014/03/04 Javascript
jQuery异步获取json数据方法汇总
2014/12/22 Javascript
jquery实现平滑的二级下拉菜单效果
2015/08/26 Javascript
浅谈js图片前端预览之filereader和window.URL.createObjectURL
2016/06/30 Javascript
ES6所改良的javascript“缺陷”问题
2016/08/23 Javascript
WEB 前端开发中防治重复提交的实现方法
2016/10/26 Javascript
AngularJS使用ng-inlude指令加载页面失败的原因与解决方法
2017/01/19 Javascript
利用Node.js编写跨平台的spawn语句详解
2017/02/12 Javascript
微信小程序封装http访问网络库实例代码
2017/05/24 Javascript
JavaScript实现自动跳转文本功能
2017/05/25 Javascript
详解vue项目构建与实战
2017/06/27 Javascript
从零开始最小实现react服务器渲染详解
2018/01/26 Javascript
浅谈react受控组件与非受控组件(小结)
2018/02/09 Javascript
vue 中 beforeRouteEnter 死循环的问题
2019/04/23 Javascript
微信小程序清空输入框信息与实现屏幕往上滚动的示例代码
2020/06/23 Javascript
Element-ui 自带的两种远程搜索(模糊查询)用法讲解
2021/01/29 Javascript
Python实现的三层BP神经网络算法示例
2018/02/07 Python
python3实现斐波那契数列(4种方法)
2019/07/15 Python
Django admin.py 在修改/添加表单界面显示额外字段的方法
2019/08/22 Python
从pandas一个单元格的字符串中提取字符串方式
2019/12/17 Python
基于django micro搭建网站实现加水印功能
2020/05/22 Python
CSS3+HTML5+JS 实现一个块的收缩与展开动画效果
2020/11/17 HTML / CSS
荷兰牛仔裤网上商店:Jeans Centre
2018/04/03 全球购物
水上运动奥特莱斯:Wasterports Outlet
2018/08/08 全球购物
英国PC组件和在线电脑商店:SCAN
2019/04/18 全球购物
个人作风纪律整顿整改措施
2014/10/25 职场文书
2014年资料员工作总结
2014/11/18 职场文书
淮阳太昊陵导游词
2015/02/10 职场文书
2016年小学生寒假总结
2015/10/10 职场文书
您对思维方式了解多少?
2019/12/09 职场文书