Socket---基于IO复用实现异步非阻塞通信 Python群聊工具
2015-12-28 19:48
721 查看
运行环境:
1. 需要安装最新的python3
sudo apt-get install python3
2.
不要用ssh shell工具连接linux机器,因为它唯一缺点就是不支持中文
可以选择使用putty连接linux,编码设置使用utf8编码,这样就可以输入中文了
运行方法:
1. 将附件脚本拷贝到linux中
2. 在linux命令行下输入:python3 client.py
3. 看到Connection established, you can input to talk now, enjoy your time! 后可以输入说话的内容了
待改进地方:
1. UI取代命令行
2. 更多的异常处理
服务器端程序:
客户端程序:
1. 需要安装最新的python3
sudo apt-get install python3
2.
不要用ssh shell工具连接linux机器,因为它唯一缺点就是不支持中文
可以选择使用putty连接linux,编码设置使用utf8编码,这样就可以输入中文了
运行方法:
1. 将附件脚本拷贝到linux中
2. 在linux命令行下输入:python3 client.py
3. 看到Connection established, you can input to talk now, enjoy your time! 后可以输入说话的内容了
待改进地方:
1. UI取代命令行
2. 更多的异常处理
服务器端程序:
import socket import signal import select MAX_LISTEN_N = 100 MAX_BUFFER_N = 1024 mconnections = {} addresses = {} datalist = {} IP_ADDR = '192.168.1.2' PORT = 4547 def remove_fd_data(fd): mconnections.pop(fd) addresses.pop(fd) datalist.pop(fd) def signal_handler(signum, frame): print("signum=",signum) def prepare_socket(): #print('prepare_socket') listen_fd = socket.socket(socket.AF_INET, socket.SOCK_STREAM,0) listen_fd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,True) listen_fd.bind((IP_ADDR,PORT)) listen_fd.listen(MAX_LISTEN_N) signal.signal(signal.SIGILL,signal_handler) signal.signal(signal.SIGPIPE,signal_handler) return listen_fd def handle_accept(listen_fd,epoll_fd): client_socket,(client_addr,client_port) = listen_fd.accept() print('accept a new client:',client_socket.fileno()) epoll_fd.register(client_socket.fileno(),select.EPOLLIN) mconnections[client_socket.fileno()]=client_socket addresses[client_socket.fileno()]=client_addr datalist[client_socket.fileno()]='' def handle_read(fd,epoll_fd): print('handle_read:',fd) data_s='' while True: data=mconnections[fd].recv(MAX_BUFFER_N) #print(data) if not data and not data_s: epoll_fd.unregister(fd) mconnections[fd].close() remove_fd_data(fd) print("Client is closed abnormally:",fd) return elif len(data)==MAX_BUFFER_N: data_s+=data.decode('utf-8') continue else: data_s+=data.decode('utf-8') break #print("receive new data:",data_s) datalist[fd]=data_s epoll_fd.modify(fd,select.EPOLLOUT) def handle_write_single(epoll_fd, fd, talk): print("handle_write_single:", fd) slen = 0 while True: slen+=mconnections[fd].send(talk[slen:]) if slen == len(talk): #print('send finished') break else: print('send continue') break epoll_fd.modify(fd,select.EPOLLIN) def get_host_name(fd): name,alias,ips = socket.gethostbyaddr(addresses[fd]) if len(ips)>0: return ips[0] else: return 'Unknown name' def handle_write(fd,epoll_fd): #print('handle_write') mset = mconnections.keys() #length = len(mset) #print("length:",length) ip_name = get_host_name(fd)+': ' #handle normal exit case if True == (datalist[fd] == 'exit'): print("Client want to exit now:",fd) handle_write_single(epoll_fd,fd,datalist[fd].encode('utf-8')) epoll_fd.unregister(fd) mconnections[fd].close() remove_fd_data(fd) return for item in mset: print(fd,":",item) if fd == item: print('ignore itself') else: handle_write_single(epoll_fd,item,(ip_name+datalist[fd]).encode('utf-8')) epoll_fd.modify(fd,select.EPOLLIN) def handle_events(poll_list, listen_fd,epoll_fd): #print('handle_events') for fd, events in poll_list: if fd == listen_fd.fileno() and events==select.EPOLLIN: handle_accept(listen_fd, epoll_fd) elif events==select.EPOLLIN: handle_read(fd,epoll_fd) elif events==select.EPOLLOUT: handle_write(fd,epoll_fd) elif events==select.EPOLLHUP: print("Client is closed:",fd) epoll_fd.unregister(fd) mconnections[fd].close() remove_fd_data(fd) else: continue def prepare_epoll(listen_fd): #print('prepare_epoll') epoll_fd = select.epoll() epoll_fd.register(listen_fd.fileno(),select.EPOLLIN) while True: poll_list = epoll_fd.poll(-1,-1) handle_events(poll_list, listen_fd,epoll_fd) epoll_fd.close() if __name__ == '__main__': listen_fd=prepare_socket() prepare_epoll(listen_fd) listen_fd.close()
客户端程序:
import socket import signal import select import threading MAX_BUFFER_N = 1024 IP_ADDR = '192.168.1.2' PORT = 4547 epoll_obj = {} def exit_client(socket_obj): epoll_obj[0].unregister(0) def init_socket(): return socket.socket(socket.AF_INET, socket.SOCK_STREAM,0) def prepare_socket(socket_obj): socket_obj.connect((IP_ADDR,PORT)) w_msg = '''Connection established, you \ can input to talk now, enjoy your time!''' print(w_msg) def handle_read(socket_obj,fd): #print('handle_read') data_s='' is_exit = False while True: data=socket_obj.recv(MAX_BUFFER_N) #print(data) if not data and not data_s: epoll_obj[1].unregister(fd) print('error when read') is_exit = True return is_exit elif len(data)==100: data_s+=data.decode('utf-8') continue else: data_s+=data.decode('utf-8') break if True == ('exit' == data_s): epoll_obj[1].unregister(fd) is_exit = True print('I will exit now, see you later') return is_exit print(' ',data_s) return is_exit def handle_write_for_0(socket_obj,fd): #print('handle_write_for_0') is_exit = False data = input() socket_obj.send(data.encode('utf-8')) if True == ('exit' == data): is_exit = True epoll_obj[0].unregister(0) return is_exit def handle_events(socket_obj,poll_list): #print('handle_events') is_exit = False for fd, events in poll_list: #print("fd:",fd) if fd == 0: if events==select.EPOLLIN: continue elif events==select.EPOLLOUT: is_exit = handle_write_for_0(socket_obj,fd) elif events==select.EPOLLHUP: print("close:",fd) epoll_obj[0].unregister(fd) is_exit = True else: continue else: if events==select.EPOLLIN: is_exit = handle_read(socket_obj,fd) elif events==select.EPOLLOUT: continue elif events==select.EPOLLHUP: print("close:",fd) epoll_obj[1].unregister(fd) is_exit = True else: continue return is_exit def start_p(socket_obj): #print("start_p") epoll_obj[0] = select.epoll() epoll_obj[0].register(0,select.EPOLLOUT) while True: poll_list = epoll_obj[0].poll(-1,-1) is_exit = handle_events(socket_obj,poll_list) if is_exit==True: break epoll_obj[0].close() #print("leave start_p") def process_input(socket_obj): #print("process_input") t1 = threading.Thread(group=None,target=start_p, args=(socket_obj,)) t1.start() #print("leave process_input") def prepare_epoll(socket_obj): #print('prepare_epoll') epoll_obj[1] = select.epoll() epoll_obj[1].register(socket_obj.fileno(),select.EPOLLIN) while True: poll_list = epoll_obj[1].poll(-1,-1) is_exit = handle_events(socket_obj,poll_list) if is_exit==True: break epoll_obj[1].close() #print("leave prepare_epoll") if __name__ == '__main__': socket_obj=init_socket() prepare_socket(socket_obj) process_input(socket_obj) prepare_epoll(socket_obj) socket_obj.close()
相关文章推荐
- python的开发手册 pydoc
- python中for语句使用
- Python基础第二篇
- python
- 使用python2时会遇到一系列显示中文字符的问题
- Python 中嵌入MFC的DLL实例
- python Slope one
- Python整数的缓存
- python知识-类的继承
- Python之斐波拉数列
- day10 python学习随笔
- 第一章:Python基础知识
- 使用python爬虫抓站的一些技巧总结:进阶篇
- Python进阶之路---1.2python版本差异
- Python编辑器安装
- Python安装setuptools的脚本
- Python 安装matplotlib,six,dateutil,pyparsing 完整过程
- Python文件写到本地
- MFC 使用Python脚本语言
- 【python】配置文件