单进程服务器

from socket import *
serSocket = socket(AF_INET,SOCK_STREAM)
#重复使用绑定的信息
serSocket.setsockopt(sol_socket,so_reuseaddr,1)    #四次挥手,服务器先结束,而且想立即运行服务器,还能绑定
localAddr = ("",7788)
serSocket.bind(localAddr)
serSocket.listen(5)
while True:
    print("-----主进程,等待新客户端的到来-----")
    newSocket,destAddr = serSocket.accept()
    print("-----主进程,接下来负责数据处理")
    try:
        while True:
            recvData = newSocket.recv(1024)
            if len(recvData)>0:
                print('recv[%s]:%s'%(str(destAddr),recvData))
            else:
                print('[%s]客户端已经关闭'%str(destAddr))
                break
    finally:
        newSocket.close()
serSocket.close()

多进程服务器:

from socket import *
from multiprocessing import *
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 = Process(target = dealWithClient,args=(newSocket,destAddr))
            client.start()
#因为已经向子进程中copy了一份(引用),并且父进程中这个套接字也没有用处了,所以关闭 newSocket.close()
finally: serSocket.close() if __name__ == "__main__": main()

多线程服务器:

from socket import *
from multiprocessing import *
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()

单进程服务器-非阻塞模式

from socket import *
from multiprocessing import *
from time import sleep

serSocket = socket(AF_INET,SOCK_STREAM)
#重复使用绑定的信息

localAddr = ("",7788)
serSocket.bind(localAddr)
#让这个socket变为非阻塞
serSocket.setblocking(False)
serSocket.listen(100)
clientAddrList = []   #用来保存所有已经连接的客户端的信息
while True:
    try:
        clientSocket,clientAddr = serSocket.accept()    
    except:
        pass
    else:
        print("一个新的客户端到来:%s"%str(clientAddr))
        clientAddrList.append((newSocket,clientAddr))
    for clientSocket,clientAddr in clientAddrList:
        try:
            recvData = clientSocket.recv(1024)
        except:
            pass
        else:
            if len(recvData)>0:
                print("%s:%s"%(str(clientAddr),recvData))
            else:
                clientSocket.close()
                clientAddrList.remove((clientSocket,clientAddr))
                print("%s已经下线"%str(clientAddr))

select版服务器

import select
import socket
import sys

server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(("",7788))
server.listen(5)
inputs = [server,sys.stdin]
running = True
while True:
    # 调用 select 函数,阻塞等待
    readable,writeable,exceptional = select.select(inputs,[],[])
    # 数据抵达,循环
    for sock in readable:
        # 监听到有新的连接
        if sock == server:
            conn,addr = server.accept()
            # select 监听的socket
            inputs.append(conn)
        # 监听到键盘有输入
        elif sock == sys.stdin:
            cmd = sys.stdin.readline()
            running = False
        # 有数据到达    
        else:
            # 读取客户端连接发送的数据
            data = sock.recv(1024)
            if data:
                sock.send(data)
            else:
                # 移除select监听的socket
                inputs.remove(sock)
                sock.close()
    # 如果检测到用户输入敲击键盘,那么就退出
    if not running:
        break
server.close()

epoll版服务器

import socket
import select

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind(("",7788))
s.listen(10)
epoll = select.epoll()
# 文件描述符 fileno 
epoll.register(s.fileno(),select.EPOLLIN|select.EPOLLET)
connections = {}
addresses = {}
while True:
    #epoll进行fd扫描的地方---未指定超时时间则为阻塞等待
    epoll_list = epoll.poll()
    #对事件进行判断
    for fd,events  in epoll_list:
        #如果是socket创建的套接字被激活
        if fd == s.fileno():
            conn,addr = s.accept()
            print('有新的客户端到来%s'%str(addr))
            #将conn和addr信息分别保存起来
            connections[conn.fileno()] = conn
            addresses[conn.fileno()] =addr
            #向epoll中注册连接socket的可读事件
            epoll.register(conn.fileno(),select.EPOLLIN|select.EPOLLET)
        elif events == select.EPOLLIN:  #判断事件是否是接收数据的事件
            #从激活fd上接收
            recvData = connections[fd].revc(1024)
            if len(recvData)>0:
                print('recv:%s'%recvData)
            else:
                epoll.unregister(fd)
                connections[fd].close()
                print("%s---offline---"%str(addresses[fd]))

协程

import time
def A():
    while True:
        print("----A----")
        yield
        time.sleep(0.5)
def B(c):
    while True:
        print("----B----")
        next(c)
        time.sleep(0.5)
if __name__ == "__main__":
    a = A()
    B(a)

greenlet实现多任务

sudo pip3 install greenlet

协程由开发者决定什么时候切,而进程、线程由操作系统决定什么时候切

from greenlet import greenlet
import time

def test1():
    while True:
        print("-----A-----")
        gr2.switch()
        time.sleep(0.5)
def test2():
    while True:
        print("-----B-----")
        gr1.switch()
        time.sleep(0.5)
gr1 = greenlet(test1)
gr2 = greenlet(test2)

gr1.switch()

gevent版服务器

sudo pip3 install gevent

import gevent
def f(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        gevent.sleep(1)
g1 = gevent.spawn(f,5)
g2 = gevent.spawn(f,5)
g3 = gevent.spawn(f,5)
g1.join()
g2.join()
g3.join()

gevent版-tcp服务器

import sys
import time
import gevent
from gevent import socket,monkey
monkey.patch_all()   #打补丁,把python代码改掉,耗时操作切换
def handle_request(conn):
    while True:
        data = conn.recv(1024)
        if not data:
            conn.close()
            break
        print("recv",data)
        conn.send(data)
def server(port):
    s = socket.socket()
    s.bind(("",port))
    s.listen(5)
    while True:
        cli,addr = s.accept()
        gevent.spawn(handle_request,cli)
if __name__ == '__main__':
    server(7788)

优质内容筛选与推荐>>
1、js学习之原型prototype(一)
2、客户端开发流程
3、LATEX Mathematical Symbols
4、2017.3.27下午学习报告
5、spring-ioc


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn