首页 > 代码库 > 【Python】iichats —— 命令行下的局域网聊天程序

【Python】iichats —— 命令行下的局域网聊天程序

转载请声明出处: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 = http://www.mamicode.com/data[5:] 30         res = data.split(#opt:) 31         return res 32     def makebc(self, name, switch): 33         data = http://www.mamicode.com/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 =http://www.mamicode.com/ 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 =http://www.mamicode.com/ 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 =http://www.mamicode.com/ 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 = True111 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 =http://www.mamicode.com/ Data()119         self.thread_stop = False120     def ans(self, addr):#to be added 用来确认消息报的接受121         return122     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 msg132                 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 = True138 139 #启动入口类140 class Start(): 141     def __init__(self):142         self.name = socket.getfqdn(socket.gethostname())143         self.data =http://www.mamicode.com/ Data()144         self.listen = Listen()145         self.back = Back()146         print *******   iichats   ********147         print      Written by Kevince     \n148         print This is  + self.name149         print self.data.gettime()+\n150     #帮助信息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 key165             print **********************\n166             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 anoun175         global START176         while True:177             arg = raw_input(START)178             if arg[0:5] == :quit and START != INIT:179                 name = ‘‘180                 address = ‘‘181                 START = INIT182             elif arg[0] == : and START == INIT:183                 if arg[1:] == exit:184                     break185                 elif arg[1:5] == list:186                     self.refresh()187                     continue188                 elif arg[1:12] == set status :189                     if arg[12:] == on:190                         anoun = 1191                     elif arg[12:] == off:192                         anoun = 0193                     continue194                 elif arg[1:5] == help:195                     self.helpinfo()196                     continue197                 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 exist212                             outmutex.release()213                         continue214                     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 + INIT218                         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                     continue229                 data =http://www.mamicode.com/ arg230                 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 = 1247 s = Start()248 s.start()

 

【Python】iichats —— 命令行下的局域网聊天程序