单进程-非阻塞服务器

from socket import *
#1.创建socket
serSocket = socket(AF_INET, SOCK_STREAM)

#2. 绑定本地ip以及port
localAddr = (‘‘, 7788)
serSocket.bind(localAddr)

#3. 让这个socket 变为非堵塞
serSocket.setblocking(False)

#4. 将socket变为监听(被动)套接字
serSocket.listen(100)

# 用来保存所有已经连接的客户端的信息
clientAddrList = []

while True:

    #等待一个新的客户端的到来(即完成3次握手的客户端)
    try:
        clientSocket,clientAddr = serSocket.accept()
    except:
        pass
    else:
        print("一个新的客户端到来:%s"%str(clientAddr))
        clientSocket.setblocking(False)
        clientAddrList.append((clientSocket,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,轮询最多可监听1024个人,poll无默认值,但是也是轮询

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
            break

        # 有数据到达
        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非轮询,无限制,事件通知机制

  • EPOLLIN (可读)
  • EPOLLOUT (可写)
  • EPOLLET (ET模式)

epoll对文件描述符的操作有两种模式:LT(level trigger)和ET(edge trigger)。LT模式是默认模式,LT模式与ET模式的区别如下:

LT模式:当epoll检测到描述符事件发生并将此事件通知应用程序,应用程序可以不立即处理该事件。下次调用epoll时,会再次响应应用程序并通知此事件。

ET模式:当epoll检测到描述符事件发生并将此事件通知应用程序,应用程序必须立即处理该事件。如果不处理,下次调用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对象
epoll=select.epoll()

# 测试,用来打印套接字对应的文件描述符
# print s.fileno()
# print select.EPOLLIN|select.EPOLLET

# 注册事件到epoll中
# epoll.register(fd[, eventmask])
# 注意,如果fd已经注册过,则会发生异常
# 将创建的套接字添加到epoll的事件监听中
epoll.register(s.fileno(),select.EPOLLIN|select.EPOLLET)

connections = {}
addresses = {}

# 循环等待客户端的到来或者对方发送数据
while True:

    # epoll 进行 fd 扫描的地方 -- 未指定超时时间则为阻塞等待
    epoll_list=epoll.poll()

    # 对事件进行判断
    for fd,events in epoll_list:

        # print fd
        # print events

        # 如果是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].recv(1024)

            if len(recvData)>0:
                print(‘recv:%s‘%recvData)
            else:
                # 从 epoll 中移除该 连接 fd
                epoll.unregister(fd)

                # server 侧主动关闭该 连接 fd
                connections[fd].close()

                print("%s---offline---"%str(addresses[fd]))
时间: 2024-10-09 22:50:02

单进程-非阻塞服务器的相关文章

Select单进程非阻塞TCP echo服务器

1. select 描述 #include <sys/select.h> #include <sys/time.h> int select( int maxfdp1,   fd_set *readset,  fd_set *writeset,  fd_set *exceptset,  const struct timeval *timeout); 返回:正确:就绪描述符数目:超时: 0:出错: -1 参数说明: timeout: 内核等待指定描述符集合中的任意一个就绪的时间. st

使用OTP原理构建一个非阻塞的TCP服务器(转)

经测试可用! 原文地址:http://www.iucai.com/?paged=8 Erlang OTP设计原理已经被shiningray兄翻译透了.请参见.http://erlang.shiningray.cn/otp-design-principles/index.html 这里翻译了一篇余锋老大和lzy.je老大推荐的文章,闲话不说,奉上. 使用OTP原理构建一个非阻塞的TCP服务器 原文网址:(打不开的同学请自觉FQ) http://www.trapexit.org.nyud.net:8

简易非阻塞http服务器

说明         需要理解阻塞和非阻塞的区别,特别要注意非阻塞和异步不是一个概念,这个很容易弄错.云盘里面netty的书会讲这几个方面的区别,nodejs深入浅出关于异步编程章节里面        也会讲到网络通信底层的知识,可以看看下面文章: http://blog.csdn.net/hguisu/article/details/7453390 http://www.cnblogs.com/dolphin0520/p/3916526.html Handler接口类 1 package st

Node.js学习笔记【1】入门(服务器JS、函数式编程、阻塞与非阻塞、回调、事件、内部和外部模块)

笔记来自<Node入门>@2011 Manuel Kiessling JavaScript与Node.js Node.js事实上既是一个运行时环境,同时又是一个库. 使用Node.js时,我们不仅仅在实现一个应用,同时还实现了整个HTTP服务器. 一个基础的HTTP服务器 server.js:一个可以工作的HTTP服务器 var http = require("http"); http.createServer(function(request, response) { r

【python】网络编程-SocketServer 实现客户端与服务器间非阻塞通信

利用SocketServer模块来实现网络客户端与服务器并发连接非阻塞通信.首先,先了解下SocketServer模块中可供使用的类:BaseServer:包含服务器的核心功能与混合(mix-in)类挂钩:这个类只用于派生,所以不会生成这个类的实例:可以考虑使用TCPServer和UDPServer.TCPServer/UDPServer:基本的网络同步TCP/UDP服务器.UnixStreamServer/ UnixDatagramServer:基本的基于文件同步TCP/UDP服务器.Fork

实现一个非阻塞IO的服务器

先来实现一个简单的服务器,这个服务器简单的回送任何客户端的输入 EchoServer.java package server; import java.io.*; import java.net.*; import java.util.*; /** * This program implements a simple server that listens to port 8189 and echoes back all client input * @author zhangchen * */

Netty:一个非阻塞的客户端/服务器框架

Netty:一个非阻塞的客户端/服务器框架 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs Netty是一个异步事件驱动的网络应用框架,为Java网络应用的开发带来了一些新活力.Netty由协议服务器和客户端所组成,可用于快速开发可维护的高性能软件.Netty应用框架及其工具简化了网络编程,而且由Netty社区进行维护. Netty还被归类为NIO客户端/服务器框架,用它能够快速.简易地开发网络应用,使得TCP和UDP套接字服务器的网络编程得以简化和

Java NIO 非阻塞Socket服务器构建

部分内容引用自xpbug的Blog. 说到socket服务器,第一反应是java.net.Socket这个类.事实上在并发和响应时间要求不高的场合,是可以用java.net.Socket来实现的,比如写一个局域网聊天工具.发送文件等.但它的缺点也很明显,需要自行对接受的线程进行维护,管理缓冲区的分配等,我尝试过用java.net.Socket完成一个瞬时负载在千人左右的服务器,却因后期改动和维护异常麻烦而放弃. Java自1.4以后,加入了新IO特性,这便是本文要介绍的NIO.下面是一段服务器的

Socket编程总结—Android手机服务器与多个Android手机客户端之间的通信(非阻塞)

根据前两周写的关于Socket编程的网络通信的代码,现在对有关知识和注意事项进行总结如下: 1.首先说下Android NIO中有关Socket编程的类: 1)ServerSocketChannel类:服务器套接字通道相当于传统IO下的ServerSocket,通过ServerSocketChannel的socket()可以获得传统的ServerSocket,反过来使用ServerSocket的getChannel()可以获得ServerSocketChannel对象:实例化ServerSock