标签:style blog http color os 使用 io ar for
转载请声明出处:http://www.cnblogs.com/kevince/p/3941728.html ——By Kevince
ii系列工具第三弹,命令行下的局域网聊天程序
原理:
程序启动时向全网(255.255.255.255)BACKPORT端口广播自己的主机名以及状态(上线)。
如果接受收到的上线状态,则将其加入通信列表,同时返还一个数据包,使自己也将对面加入其通信列表。
程序退出时向全网广播自己的下线状态,如果收到该下线状态则将其从自己的通信列表中删除
为了防止在输入过程中被新输出的消息打断,可以用readlines中的get_line_buffer函数获取缓冲区内的字符并储存,清空原先行,输出新结果,并在下面输出刚刚输入的内容(可用curses改进,to be continued...)
缺陷:
使用UDP协议,未添加消息到达确认机制;
跨平台支持需要修改代码(readlines只支持linux, windows下要用pyreadline,MAC OS要用edlitline来代替)
实用性不强,功能单一,学习程序
未能实现GUI图形界面的开发(目前还木有学会……)
刚学Python没多久 且开发仓促,有Bug还请多多指教~
1 #!/usr/bin/python 2 #coding:utf8 3 4 import threading 5 import socket 6 import time 7 import os 8 import sys 9 import signal 10 from readline import get_line_buffer 11 BUFSIZE = 1024 12 BACKPORT = 7789 #状态监听端口 13 CHATPORT = 7788 #聊天信息发送窗口 14 START = ‘>>‘ 15 INIT = ‘>>‘ 16 users = {} 17 ips = {} 18 #起到双向字典的作用,ip和name互相映射 19 20 #数据处理类(消息封装、分解) 21 class Data(): 22 def gettime(self): 23 return time.strftime(‘%Y-%m-%d %H:%M‘, time.localtime(time.time())) 24 def getip(self): 25 ip = os.popen("/sbin/ifconfig | grep ‘inet addr‘ | awk ‘{print $2}‘").read() 26 ip = ip[ip.find(‘:‘)+1:ip.find(‘\n‘)] 27 return ip 28 def handlebc(self, data): 29 data = data[5:] 30 res = data.split(‘#opt:‘) 31 return res 32 def makebc(self, name, switch): 33 data = ‘name:%s#opt:%d‘ % (name, switch) 34 return data 35 def handlechat(self, data): 36 msg = ‘\n‘ + self.gettime() + ‘\n‘ +‘from ‘+ data + ‘\n‘ 37 return msg 38 def makechat(self, data, name): 39 return name + ‘:‘ + data 40 41 #后台监听类 42 class Back(threading.Thread): 43 def __init__(self): 44 threading.Thread.__init__(self) 45 self.data = Data() 46 self.addrb = (‘255.255.255.255‘, BACKPORT) 47 self.addrl = (‘‘, BACKPORT) 48 self.name = socket.gethostname() 49 self.ip = self.data.getip() 50 self.thread_stop = False 51 def status(self, name, switch): 52 if switch == 0: 53 status = ‘offline‘ 54 elif switch == 1: 55 status = ‘online‘ 56 #用来处理输入过程中被线程返回消息打乱的情况 57 if outmutex.acquire(1): 58 sys.stdout.write(‘\r‘+‘ ‘*(len(get_line_buffer())+len(START))+‘\r‘) 59 print ‘[status] ‘+name+‘ ‘+status 60 sys.stdout.write(START+get_line_buffer()) 61 sys.stdout.flush() 62 outmutex.release() 63 def broadcast(self, switch): 64 bsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 65 bsock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) 66 data = self.data.makebc(self.name, switch) 67 bsock.sendto(data, self.addrb) 68 bsock.close() 69 def response(self, addr, switch): 70 rsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 71 data = self.data.makebc(self.name, switch) 72 rsock.sendto(data, (addr, BACKPORT)) 73 rsock.close() 74 def check(self): 75 if usermutex.acquire(): 76 ips.clear() 77 users.clear() 78 usermutex.release() 79 self.broadcast(1) 80 def run(self): 81 lsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 82 lsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 83 lsock.bind(self.addrl) 84 self.broadcast(1) 85 while not self.thread_stop: 86 data, addr = lsock.recvfrom(BUFSIZE) 87 datalist = self.data.handlebc(data) 88 if usermutex.acquire(1): 89 if datalist[1] == ‘0‘: 90 if ips.has_key(addr[0]): 91 if anoun == 1: 92 self.status(datalist[0], 0) 93 del ips[addr[0]] 94 del users[datalist[0]] 95 elif datalist[1] == ‘1‘: 96 if anoun == 1 and datalist[0] != self.name: 97 self.status(datalist[0], 1) 98 users[datalist[0]] = addr[0] 99 ips[addr[0]] = datalist[0] 100 self.response(addr[0], 2) 101 elif datalist[1] == ‘2‘: 102 if anoun == 1 and datalist[0] != self.name: 103 self.status(datalist[0], 1) 104 users[datalist[0]] = addr[0] 105 ips[addr[0]] = datalist[0] 106 usermutex.release() 107 lsock.close() 108 def stop(self): 109 self.broadcast(0) 110 self.thread_stop = True 111 112 #聊天类 113 class Listen(threading.Thread): 114 def __init__(self): 115 threading.Thread.__init__(self) 116 self.addr = (‘‘, CHATPORT) 117 self.name = socket.getfqdn(socket.gethostname()) 118 self.data = Data() 119 self.thread_stop = False 120 def ans(self, addr):#to be added 用来确认消息报的接受 121 return 122 def run(self): 123 lsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 124 lsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 125 lsock.bind(self.addr) 126 while not self.thread_stop: 127 data, addr = lsock.recvfrom(BUFSIZE) 128 msg = self.data.handlechat(data) 129 if outmutex.acquire(1): 130 sys.stdout.write(‘\r‘+‘ ‘*(len(get_line_buffer())+len(START))+‘\r‘) 131 print msg 132 sys.stdout.write(START+get_line_buffer()) 133 sys.stdout.flush() 134 outmutex.release() 135 lsock.close() 136 def stop(self): 137 self.thread_stop = True 138 139 #启动入口类 140 class Start(): 141 def __init__(self): 142 self.name = socket.getfqdn(socket.gethostname()) 143 self.data = Data() 144 self.listen = Listen() 145 self.back = Back() 146 print ‘******* iichats ********‘ 147 print ‘ Written by Kevince \n‘ 148 print ‘This is ‘ + self.name 149 print self.data.gettime()+‘\n‘ 150 #帮助信息 151 def helpinfo(self): 152 if outmutex.acquire(1): 153 print "use ‘:‘ to use options" 154 print "\t:exit\t\t\texit iichats" 155 print "\t:list\t\t\tlist online users" 156 print "\t:quit\t\t\tquit the chat mode" 157 print "\t:chat [hostname]\tchatting to someone" 158 print "\t:set status [on|off]\tturn on/of status alarms" 159 outmutex.release() 160 def refresh(self): 161 if outmutex.acquire(1): 162 print ‘\n******Onlinelist******‘ 163 for key in users: 164 print key 165 print ‘**********************\n‘ 166 outmutex.release() 167 def chatting(self): 168 csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 169 if outmutex.acquire(1): 170 print "use ‘:help‘ to get help information" 171 outmutex.release() 172 name = ‘‘ 173 address = ‘‘ 174 global anoun 175 global START 176 while True: 177 arg = raw_input(START) 178 if arg[0:5] == ‘:quit‘ and START != INIT: 179 name = ‘‘ 180 address = ‘‘ 181 START = INIT 182 elif arg[0] == ‘:‘ and START == INIT: 183 if arg[1:] == ‘exit‘: 184 break 185 elif arg[1:5] == ‘list‘: 186 self.refresh() 187 continue 188 elif arg[1:12] == ‘set status ‘: 189 if arg[12:] == ‘on‘: 190 anoun = 1 191 elif arg[12:] == ‘off‘: 192 anoun = 0 193 continue 194 elif arg[1:5] == ‘help‘: 195 self.helpinfo() 196 continue 197 elif arg[1:6] == ‘check‘: 198 self.back.check() 199 print ‘checking the list...‘ 200 time.sleep(3) 201 if outmutex.acquire(1): 202 outmutex.release() 203 self.refresh() 204 elif arg[1:6] == ‘chat ‘: 205 name = arg[6:] 206 if usermutex.acquire(1): 207 userlist = users.keys() 208 usermutex.release() 209 if name not in userlist: 210 if outmutex.acquire(1): 211 print ‘this host does not exist‘ 212 outmutex.release() 213 continue 214 address = (users.get(name), CHATPORT) 215 if outmutex.acquire(1): 216 print ‘now chatting to ‘ + name+" ,use ‘:quit‘ to quit CHAT mode" 217 START = name + INIT 218 outmutex.release() 219 else: 220 if outmutex.acquire(1): 221 print "invalid input, use ‘:help‘ to get some info" 222 outmutex.release() 223 else: 224 if not len(address): 225 if outmutex.acquire(1): 226 print "you can CHAT to someone, or use ‘:help‘" 227 outmutex.release() 228 continue 229 data = arg 230 msg = self.data.makechat(data, self.name) 231 csock.sendto(msg, address) 232 csock.close() 233 def start(self): 234 self.back.setDaemon(True) 235 self.back.start() 236 self.listen.setDaemon(True) 237 self.listen.start() 238 self.chatting() 239 self.back.stop() 240 self.listen.stop() 241 sys.exit() 242 243 usermutex = threading.Lock() 244 outmutex = threading.Lock() 245 #控制status on和off的情况 246 anoun = 1 247 s = Start() 248 s.start()
【Python】iichats —— 命令行下的局域网聊天程序
标签:style blog http color os 使用 io ar for
原文地址:http://www.cnblogs.com/kevince/p/3941728.html