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中操作列表之List.append()方法的使用
May 20 Python
Python实现解析Bit Torrent种子文件内容的方法
Aug 29 Python
python3学习笔记之多进程分布式小例子
Feb 13 Python
Python实现的自定义多线程多进程类示例
Mar 23 Python
查找python项目依赖并生成requirements.txt的方法
Jul 10 Python
Python多进程池 multiprocessing Pool用法示例
Sep 07 Python
python3使用print打印带颜色的字符串代码实例
Aug 22 Python
使用 Python 写一个简易的抽奖程序
Dec 08 Python
简单了解为什么python函数后有多个括号
Dec 19 Python
python怎么调用自己的函数
Jul 01 Python
Python使用MapReduce进行简单的销售统计
Apr 22 Python
python标准库ElementTree处理xml
May 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
安装apache2.2.22配置php5.4(具体操作步骤)
2013/06/26 PHP
ie与session丢失(新窗口cookie丢失)实测及解决方案
2013/07/15 PHP
PHP mail()函数使用及配置方法
2014/01/14 PHP
php统计数组元素个数的方法
2015/07/02 PHP
PHP实现微信JS-SDK接口选择相册及拍照并上传的方法
2016/12/05 PHP
javascript dom 基本操作小结
2010/04/11 Javascript
20款效果非常棒的 jQuery 插件小结分享
2011/11/18 Javascript
父节点获取子节点的字符串示例代码
2014/02/26 Javascript
不使用ajax实现无刷新提交表单
2014/12/21 Javascript
jstl中判断list中是否包含某个值的简单方法
2016/10/14 Javascript
Angular2 多级注入器详解及实例
2016/10/30 Javascript
js文件中直接alert()中文出来的是乱码的解决方法
2016/11/01 Javascript
利用JS判断字符串是否含有数字与特殊字符的方法小结
2016/11/25 Javascript
Angular.js中控制器之间的传值详解
2017/04/24 Javascript
使用layer弹窗提交表单时判断表单是否输入为空的例子
2019/09/26 Javascript
vue路由切换之淡入淡出的简单实现
2019/10/31 Javascript
python循环监控远程端口的方法
2015/03/14 Python
Python中实现参数类型检查的简单方法
2015/04/21 Python
使用Python的Bottle框架写一个简单的服务接口的示例
2015/08/25 Python
python批量实现Word文件转换为PDF文件
2018/03/15 Python
使用numpy和PIL进行简单的图像处理方法
2018/07/02 Python
python 格式化输出百分号的方法
2019/01/20 Python
正确理解Python中if __name__ == '__main__'
2019/01/24 Python
python字典的setdefault的巧妙用法
2019/08/07 Python
Python3 Tkinkter + SQLite实现登录和注册界面
2019/11/19 Python
python 比较2张图片的相似度的方法示例
2019/12/18 Python
使用Matplotlib绘制不同颜色的带箭头的线实例
2020/04/17 Python
PyQt5实现简单的计算器
2020/05/30 Python
详解html5 canvas常用api总结(二)--绘图API
2016/12/14 HTML / CSS
The North Face官方旗舰店:美国著名户外品牌
2020/09/28 全球购物
Python基于Tkinter开发一个爬取B站直播弹幕的工具
2021/05/06 Python
JavaScript实现班级抽签小程序
2021/05/19 Javascript
vue3中provide && inject的使用
2021/07/01 Vue.js
Spring Boot 整合 Apache Dubbo的示例代码
2021/07/04 Java/Android
我去timi了,一起去timi是什么意思?
2022/04/13 杂记
Spring Security动态权限的实现方法详解
2022/06/16 Java/Android