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笔记(2)
Oct 24 Python
小白如何入门Python? 制作一个网站为例
Mar 06 Python
对python For 循环的三种遍历方式解析
Feb 01 Python
python找出因数与质因数的方法
Jul 25 Python
PyQT5 emit 和 connect的用法详解
Dec 13 Python
详解Python中字符串前“b”,“r”,“u”,“f”的作用
Dec 18 Python
python list等分并从等分的子集中随机选取一个数
Nov 16 Python
Python3 用什么IDE开发工具比较好
Nov 28 Python
基于python实现监听Rabbitmq系统日志代码示例
Nov 28 Python
Pandas直接读取sql脚本的方法
Jan 21 Python
总结Python变量的相关知识
Jun 28 Python
Python将CSV文件转化为HTML文件的操作方法
Jun 30 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开发者的编程指南 第一部分降低复杂程度
2016/01/18 PHP
PHP的Yii框架中移除组件所绑定的行为的方法
2016/03/18 PHP
php array_values 返回数组的所有值详解及实例
2016/11/12 PHP
php生成HTML文件的类方法
2019/10/11 PHP
JavaScript 比较时间大小的代码
2010/04/24 Javascript
读JavaScript DOM编程艺术笔记
2011/11/15 Javascript
为什么要在引入的css或者js文件后面加参数的详细讲解
2013/05/03 Javascript
JavaScript获取IP获取的是IPV6 如何校验
2016/06/12 Javascript
基于JavaScript实现添加到购物车效果附源码下载
2016/08/22 Javascript
Angularjs 依赖压缩及自定义过滤器写法
2017/02/04 Javascript
backbone简介_动力节点Java学院整理
2017/07/14 Javascript
老生常谈js中的MVC
2017/07/25 Javascript
thinkjs 文件上传功能实例代码
2017/11/08 Javascript
js动态引入的四种方法
2018/05/05 Javascript
详解基于Node.js的HTTP/2 Server实践
2018/05/31 Javascript
jquery实现联想词搜索框和搜索结果分页的示例
2018/10/10 jQuery
详解JavaScript 高阶函数
2020/09/14 Javascript
K-means聚类算法介绍与利用python实现的代码示例
2017/11/13 Python
Python3生成手写体数字方法
2018/01/30 Python
python与C、C++混编的四种方式(小结)
2019/07/15 Python
详解用Python进行时间序列预测的7种方法
2020/03/13 Python
Django 实现对已存在的model进行更改
2020/03/28 Python
HTML5+CSS3实例 :canvas 模拟实现电子彩票刮刮乐代码
2016/12/30 HTML / CSS
印度低票价航空公司:GoAir
2017/10/11 全球购物
墨尔本照明批发商店:Mica Lighting
2017/12/28 全球购物
美国购买当代和现代家具网站:MODTEMPO
2018/07/20 全球购物
AJAX应用和传统Web应用有什么不同
2013/08/24 面试题
大学生个人推荐信范文
2013/11/25 职场文书
服务中心夜班服务员岗位职责
2013/11/27 职场文书
活动总结报告格式
2014/05/09 职场文书
党员廉洁自律承诺书
2014/05/26 职场文书
学习型班组申报材料
2014/05/31 职场文书
党员教师四风问题整改措施思想汇报
2014/10/08 职场文书
教师个人教学总结
2015/02/11 职场文书
聊一聊python常用的编程模块
2021/05/14 Python
Golang原生rpc(rpc服务端源码解读)
2022/04/07 Golang