基本思路生成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()