基本思路生成socket,绑定IP端口,listen后使用select或者kqueue管理连接是否能够读写操做。得到连接后,等待客户端输入,将从客户端收到的数据原样返回给客户端。实现基本的回显操做。python
服务端代码:缓存
# 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模式 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模式 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()