前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python实现并发http服务器

python实现并发http服务器

作者头像
不断折腾
发布2019-09-23 10:49:09
1.2K0
发布2019-09-23 10:49:09
举报
使用多进程实现http服务器

我们将上次的简单http服务器代码复制过来,在他的基础上进行修改,

我们只需要多进程执行发送寒素即可,在main中修改:

import socket

import re

import multiprocessing

def dump_data(cli_socket):

recv_data = cli_socket.recv(1024).decode('utf-8')

recv_data_lines = recv_data.splitlines()

print(recv_data_lines)

ret = re.match(r'[^/]+(/[^ ]*)',recv_data_lines[0])

if ret:

f_name = ret.group(1)

if f_name=="/":

f_name = '/index.html'

try:

file = open('F:'+f_name,'rb')

except:

resp_data = 'HTTP/1.1 404 NOT FOUND\r\n'

resp_data += 'Content-Type:text/html;charset:uft-8\r\n'

resp_data += '\r\n'

resp_data += '404'

cli_socket.send(resp_data.encode('utf-8'))

else:

html_con = file.read()

file.close()

resp_data = 'HTTP/1.1 200 OK\r\n'

resp_data += 'Content-Type:text/html;charset:uft-8\r\n'

resp_data += '\r\n'

cli_socket.send(resp_data.encode('utf-8'))

cli_socket.send(html_con)

cli_socket.close()

def main():

tcp_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

tcp_server.bind(("",7891))

tcp_server.listen(128)

print('等待')

while True:

cli_socket,cli_addr = tcp_server.accept()

# 多进程实现调用该方法

p = multiprocessing.Process(target=dump_data,args =(cli_socket,))

p.start()

# 这里也需要调用 cli_socket.close(),子进程关闭,主进程关闭。

cli_socket.close()

tcp_server.close()

if __name__ == "__main__":

main()

使用多线程实现http服务器

很简单,把进程修改成线程就可以了。这里就不需要cli_socket.close()了。

import socket

import re

import multiprocessing

def dump_data(cli_socket):

recv_data = cli_socket.recv(1024).decode('utf-8')

recv_data_lines = recv_data.splitlines()

print(recv_data_lines)

ret = re.match(r'[^/]+(/[^ ]*)',recv_data_lines[0])

if ret:

f_name = ret.group(1)

if f_name=="/":

f_name = '/index.html'

try:

file = open('F:'+f_name,'rb')

except:

resp_data = 'HTTP/1.1 404 NOT FOUND\r\n'

resp_data += 'Content-Type:text/html;charsetuft-8'

resp_data += '\r\n'

resp_data += '404'

cli_socket.send(resp_data.encode('utf-8'))

else:

html_con = file.read()

file.close()

resp_data = 'HTTP/1.1 200 OK\r\n'

resp_data += '\r\n'

cli_socket.send(resp_data.encode('utf-8'))

cli_socket.send(html_con)

cli_socket.close()

def main():

tcp_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

tcp_server.bind(("",7891))

tcp_server.listen(128)

print('等待')

while True:

cli_socket,cli_addr = tcp_server.accept()

# 多进程实现调用该方法

p = multiprocessing.Process(target=dump_data,args =(cli_socket,))

p.start()

# 这里也需要调用 cli_socket.close(),子进程关闭,主进程关闭。

cli_socket.close()

tcp_server.close()

if __name__ == "__main__":

main()

用gevent实现http服务器

这里就不贴全部代码了,在前面添加:

from gevent import monkey

monkey.patch_all()

main方法修改成:

def main():

tcp_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

tcp_server.bind(("",7891))

tcp_server.listen(128)

print('等待')

while True:

cli_socket,cli_addr = tcp_server.accept()

# gevent实现

gevent.spawn(dump_data,cli_socket)

tcp_server.close()

即可。

单进程,单线程,非堵塞实现并发

上面只有以用多线程,多进程,是因为会发生堵塞的情况,那我们用单进程,单线程,能不能实现不不堵塞不就好了。

设置套接字非堵塞:套接字.setblocking(False),但是不堵塞后,没有收到数据,就会报错的。报错我们处理错误就好了。

实例:

import socket

import re

import time

def main():

tcp_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

tcp_server.bind(("",7891))

tcp_server.listen(128)

# 设置非堵塞

tcp_server.setblocking(False)

# 创建一个列表

server_tcp_list = list()

while True:

time.sleep(1)

try:

cli_socket,cli_addr = tcp_server.accept()

except Exception as e:

print('等待连接')

else:

cli_socket.setblocking(False)

print('来了一个客户端')

server_tcp_list.append(cli_socket)

for cli_soc in server_tcp_list:

try:

recv_data = cli_soc.recv(1024).decode('utf-8')

except Exception as e:

print('等待发送过来数据')

else:

if recv_data:

print('有数据')

else:

print('服务完成')

cli_soc.close()

server_tcp_list.remove(cli_soc)

tcp_server.close()

if __name__ == "__main__":

main()

长连接与短连接

在HTTP协议1.0中是短连接,在1.1中是长连接

什么是长连接和短连接。

短连接:我们向服务器请求一个数据,先发送请求,再断开,如果再想要一个数据,就再次请求,断开。

长链接:在一起连接和断开中,请求多个数据。

我们上面的例子看是http1.1协议,是长链接,但是我们每次请求后都调用了close(),也就变成了短连接。

长链接实现:

import socket

import re

def dump_data(cli_socket,recv_data):

recv_data_lines = recv_data.splitlines()

print(recv_data_lines)

ret = re.match(r'[^/]+(/[^ ]*)',recv_data_lines[0])

if ret:

f_name = ret.group(1)

if f_name=="/":

f_name = '/index.html'

try:

file = open('F:'+f_name,'rb')

except:

resp_data = 'HTTP/1.1 404 NOT FOUND\r\n'

resp_data += '\r\n'

resp_data += '404'

cli_socket.send(resp_data.encode('utf-8'))

else:

html_con = file.read()

file.close()

resp_data = 'HTTP/1.1 200 OK\r\n'

# 设置编码

resp_data += 'Content-Type:text/html;charset:uft-8\r\n'

# 设置发送的长度,不关闭套接字不知道客户端数据是否发送完毕,设置body长度,body发送完,就发送完毕

resp_data += 'Content-Length:%d\r\n'%(len(html_con))

resp_data += '\r\n'

cli_socket.send(resp_data.encode('utf-8'))

cli_socket.send(html_con)

def main():

tcp_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

tcp_server.bind(("",7891))

tcp_server.listen(128)

# 设置非堵塞

tcp_server.setblocking(False)

# 创建一个列表

server_tcp_list = list()

print('等待')

while True:

try:

cli_socket,cli_addr = tcp_server.accept()

except Exception as e:

pass

else:

cli_socket.setblocking(False)

server_tcp_list.append(cli_socket)

for cli_soc in server_tcp_list:

try:

recv_data = cli_soc.recv(1024).decode('utf-8')

except Exception as e:

pass

else:

if recv_data:

dump_data(cli_soc,recv_data)

else:

cli_soc.close()

server_tcp_list.remove(cli_soc)

tcp_server.close()

if __name__ == "__main__":

main()

实现并发服务器的 另一种方式

epoll:

感兴趣的可以去了解下,他的效率很高。nginx服务器一定用到了epoll。gevent内部也用到了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-12-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 python入门到放弃 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档