python socket epoll_python下的socket学习,包括select, epoll,kqueue

服务端:

基本思路生成socket,绑定IP端口,listen后使用select或者kqueue管理链接是否可以读写操作。获得链接后,等待客户端输入,将从客户端收到的数据原样返回给客户端。实现基本的回显操作。

服务端代码:

select模式

# coding=utf-8

__author__ = 'chenglp'

"""socket,select, kqueue学习

"""

import socket

import select

import sys

HOST = '127.0.0.1'

PORT = 8001

BUFFER_SIZE = 1024

#生成socket,绑定ip端口

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

server.bind((HOST, PORT))

server.listen(5)

#创建输入监听列表

inputs = [server, sys.stdin]

#select模式

def select_mode():

running = True

while running:

try:

#select轮询inputs列表获取可以读的描述符

readable, writeable, exceptional = select.select(inputs,[],[])

except select.error as e:

break

for each in readable:

#如果是server,则accept创建链接,并将链接的描述符放入到inputs进行select监听

if each == server:

conn, addr = server.accept()

inputs.append(conn)

#如果是系统输入,则获取系统输入,停止程序

elif each == sys.stdin:

junk = sys.stdin.readline()

running = False

#如果是其它的,则为socket链接,读取链接数据,并返回读取到的数据。

else:

try:

data = each.recv(BUFFER_SIZE)

if data:

each.send(data)

if data.endswith('\r\n\r\n'):

inputs.remove(each)

each.close()

else:

inputs.remove(each)

each.close()

except socket.error as e:

inputs.remove(each)

server.close()

epoll模式:

#epoll模式

def epoll_mode():

running = True

epoll = select.epoll()

#注册epoll读

epoll.register(server.fileno(), select.EPOLLIN)

#保存链接文件描述符和链接的对应关系

conn_list = {}

while running:

try:

#开始执行epoll

events = epoll.poll(1)

except:

break

if events:

for fileno, event in events:

#如果是新链接,则accept,并将新链接注册到epoll中

if fileno == server.fileno():

conn, addr = server.accept()

conn.setblocking(0)

epoll.register(conn.fileno(), select.EPOLLIN)

conn_list[conn.fileno()] = conn

#如果是其他的可读链接,则获取到链接,recv数据,如果是\n, 则close,并从epoll中unregister掉这个文件描述符

elif event == select.EPOLLIN:

data = conn_list[fileno].recv(BUFFER_SIZE)

if data.startswith('\n'):

conn_list[fileno].close()

epoll.unregister(fileno)

del(conn_list[fileno])

else:

conn_list[fileno].send(data)

server.close()

kqueue模式:

#kqueue模式

def kqueue_mode():

running = True

kq = select.kqueue()

conn_list = {}

index = 1

#生成kevents列表,监听socket的读操作

events = [

select.kevent(server.fileno(), select.KQ_FILTER_READ,select.KQ_EV_ADD),

]

while running:

try:

#开始kqueue,如果有可执行kevent,则返回对应的kevent列表

eventlist = kq.control(events,1)

except select.error as e:

break

if eventlist:

for each in eventlist:

#如果是socket链接,则accept,将conn创建kevent放入到events进行监听,将链接放入到conn_list进行保存,key为index。

if each.ident == server.fileno():

conn, addr = server.accept()

conn_list[index] = conn

events.append(select.kevent(conn_list[index].fileno(), select.KQ_FILTER_READ, select.KQ_EV_ADD,udata=index))

index += 1

else:

try:

#如果不是socket链接,则获取到conn,然后进行读写操作。

if each.udata >= 1 and each.flags == select.KQ_EV_ADD and each.filter == select.KQ_FILTER_READ:

conn = conn_list[each.udata]

data = conn.recv(BUFFER_SIZE)

if data.startswith('\n'):

conn.close()

events.remove(select.kevent(conn_list[each.udata].fileno(), select.KQ_FILTER_READ,

select.KQ_EV_ADD,udata=each.udata))

del(conn_list[each.udata])

else:

conn.send(data)

except:

pass

server.close()

客户端:

# coding=utf-8

import socket

import select

import sys

HOST = '127.0.0.1'

PORT = 8001

BUFFER_SIZE = 1024

# 创建socket链接,链接服务器

s = socket.socket()

try:

s.connect((HOST, PORT))

except socket.error as e:

print e

#创建读写监听列表

readlist = [s, sys.stdin]

writelist = [s, ]

#输入缓存

writeCache = []

while True:

try:

#select监听获取可读可写

readable, writeabel, exceptional = select.select(readlist, writelist, [])

except select.error as e:

break

for each in readable:

#如果是系统输入,则获取输入信息放到输入缓存里

if each == sys.stdin:

inputs = sys.stdin.readline()

writeCache.append(inputs)

#如果是socket,则接受数据

elif each == s:

data = s.recv(BUFFER_SIZE)

print data

else:

pass

for each in writeabel:

#如果是socket并且写缓存有数据,则发送数据

if each == s and writeCache:

s.sendall(writeCache.pop())

s.close()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值