zoukankan      html  css  js  c++  java
  • 【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 #python 2.7.6
      4 
      5 import threading
      6 import socket
      7 import time
      8 import os
      9 import sys
     10 import signal
     11 from readline import get_line_buffer
     12 BUFSIZE = 1024
     13 BACKPORT = 7789     #状态监听端口
     14 CHATPORT = 7788     #聊天信息发送窗口
     15 START = '>>'
     16 INIT = '>>'
     17 users = {}
     18 ips = {} 
     19 #起到双向字典的作用,ip和name互相映射
     20 
     21 #数据处理类(消息封装、分解)
     22 class Data(): 
     23     def gettime(self):
     24         return time.strftime('%Y-%m-%d %H:%M', time.localtime(time.time()))
     25     def getip(self):
     26         ip = os.popen("/sbin/ifconfig | grep 'inet addr' | awk '{print $2}'").read()
     27         ip = ip[ip.find(':')+1:ip.find('
    ')]
     28         return ip
     29     def handlebc(self, data):
     30         data = data[5:]
     31         res = data.split('#opt:')
     32         return res
     33     def makebc(self, name, switch):
     34         data = 'name:%s#opt:%d' % (name, switch)
     35         return data
     36     def handlechat(self, data):
     37         msg = '
    ' + self.gettime() + '
    ' +'from '+ data + '
    '
     38         return msg
     39     def makechat(self, data, name):
     40         return name + ':' + data
     41 
     42 #后台监听类
     43 class Back(threading.Thread): 
     44     def __init__(self):
     45         threading.Thread.__init__(self)
     46         self.data = Data()
     47         self.addrb = ('255.255.255.255', BACKPORT)
     48         self.addrl = ('', BACKPORT)
     49         self.name = socket.gethostname()
     50         self.ip = self.data.getip()
     51         self.thread_stop = False
     52     def status(self, name, switch):
     53         if switch == 0:
     54             status = 'offline'
     55         elif switch == 1:
     56             status = 'online'
     57         #用来处理输入过程中被线程返回消息打乱的情况
     58         if outmutex.acquire(1):
     59             sys.stdout.write('
    '+' '*(len(get_line_buffer())+len(START))+'
    ')
     60             print '[status] '+name+' '+status
     61             sys.stdout.write(START+get_line_buffer())
     62             sys.stdout.flush()
     63             outmutex.release()
     64     def broadcast(self, switch):
     65         bsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
     66         bsock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
     67         data = self.data.makebc(self.name, switch)
     68         bsock.sendto(data, self.addrb)
     69         bsock.close()
     70     def response(self, addr, switch):
     71         rsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
     72         data = self.data.makebc(self.name, switch)
     73         rsock.sendto(data, (addr, BACKPORT))
     74         rsock.close()
     75     def check(self):
     76         if usermutex.acquire():
     77             ips.clear()
     78             users.clear()
     79             usermutex.release()
     80         self.broadcast(1)
     81     def    run(self):
     82         lsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
     83         lsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
     84         lsock.bind(self.addrl)
     85         self.broadcast(1)
     86         while not self.thread_stop:
     87             data, addr = lsock.recvfrom(BUFSIZE)
     88             datalist = self.data.handlebc(data)
     89             if usermutex.acquire(1):
     90                 if datalist[1] == '0':
     91                     if ips.has_key(addr[0]):
     92                         if anoun == 1:
     93                             self.status(datalist[0], 0)
     94                         del ips[addr[0]]
     95                         del users[datalist[0]]
     96                 elif datalist[1] == '1':
     97                     if anoun == 1 and datalist[0] != self.name:
     98                         self.status(datalist[0], 1)
     99                     users[datalist[0]] = addr[0]
    100                     ips[addr[0]] = datalist[0]
    101                     self.response(addr[0], 2)
    102                 elif datalist[1] == '2':
    103                     if anoun == 1 and datalist[0] != self.name:
    104                         self.status(datalist[0], 1)
    105                     users[datalist[0]] = addr[0]
    106                     ips[addr[0]] = datalist[0]
    107                 usermutex.release()
    108         lsock.close()
    109     def stop(self):
    110         self.broadcast(0)
    111         self.thread_stop = True
    112 
    113 #聊天类
    114 class Listen(threading.Thread):
    115     def __init__(self):
    116         threading.Thread.__init__(self)
    117         self.addr = ('', CHATPORT)
    118         self.name = socket.getfqdn(socket.gethostname())
    119         self.data = Data()
    120         self.thread_stop = False
    121     def ans(self, addr):#to be added 用来确认消息报的接受
    122         return
    123     def run(self):
    124         lsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    125         lsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    126         lsock.bind(self.addr)
    127         while not self.thread_stop:
    128             data, addr = lsock.recvfrom(BUFSIZE)
    129             msg = self.data.handlechat(data)
    130             if outmutex.acquire(1):
    131                 sys.stdout.write('
    '+' '*(len(get_line_buffer())+len(START))+'
    ')
    132                 print msg
    133                 sys.stdout.write(START+get_line_buffer())
    134                 sys.stdout.flush()
    135                 outmutex.release()
    136         lsock.close()
    137     def stop(self):
    138         self.thread_stop = True
    139 
    140 #启动入口类
    141 class Start(): 
    142     def __init__(self):
    143         self.name = socket.getfqdn(socket.gethostname())
    144         self.data = Data()
    145         self.listen = Listen()
    146         self.back = Back()
    147         print '*******   iichats   ********'
    148         print '     Written by Kevince     
    '
    149         print 'This is ' + self.name
    150         print self.data.gettime()+'
    '
    151     #帮助信息
    152     def helpinfo(self):     
    153         if outmutex.acquire(1):
    154             print "use ':' to use options"
    155             print "	:exit			exit iichats"
    156             print "	:list			list online users"
    157             print "	:quit			quit the chat mode"
    158             print "	:chat [hostname]	chatting to someone"
    159             print "	:set status [on|off]	turn on/of status alarms"
    160             outmutex.release()
    161     def refresh(self):
    162         if outmutex.acquire(1):
    163             print '
    ******Onlinelist******'
    164             for key in users:
    165                 print key
    166             print '**********************
    '
    167             outmutex.release()
    168     def chatting(self):
    169         csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    170         if outmutex.acquire(1):
    171             print "use ':help' to get help information"
    172             outmutex.release()
    173         name = ''
    174         address = ''
    175         global anoun
    176         global START
    177         while True:
    178             arg = raw_input(START)
    179             if arg[0:5] == ':quit' and START != INIT:
    180                 name = ''
    181                 address = ''
    182                 START = INIT
    183             elif arg[0] == ':' and START == INIT:
    184                 if arg[1:] == 'exit':
    185                     break
    186                 elif arg[1:5] == 'list':
    187                     self.refresh()
    188                     continue
    189                 elif arg[1:12] == 'set status ':
    190                     if arg[12:] == 'on':
    191                         anoun = 1
    192                     elif arg[12:] == 'off':
    193                         anoun = 0
    194                     continue
    195                 elif arg[1:5] == 'help':
    196                     self.helpinfo()
    197                     continue
    198                 elif arg[1:6] == 'check':
    199                     self.back.check()
    200                     print 'checking the list...'
    201                     time.sleep(3)
    202                     if outmutex.acquire(1):
    203                         outmutex.release()
    204                     self.refresh()
    205                 elif arg[1:6] == 'chat ':
    206                     name = arg[6:]
    207                     if usermutex.acquire(1):
    208                         userlist = users.keys()
    209                         usermutex.release()
    210                     if name not in userlist:
    211                         if outmutex.acquire(1):
    212                             print 'this host does not exist'
    213                             outmutex.release()
    214                         continue
    215                     address = (users.get(name), CHATPORT)
    216                     if outmutex.acquire(1):
    217                         print 'now chatting to ' + name+" ,use ':quit' to quit CHAT mode"
    218                         START = name + INIT
    219                         outmutex.release()
    220                 else:
    221                     if outmutex.acquire(1):
    222                         print "invalid input, use ':help' to get some info"
    223                         outmutex.release()
    224             else:
    225                 if not len(address):
    226                     if outmutex.acquire(1):
    227                         print "you can CHAT to someone, or use ':help'"
    228                         outmutex.release()
    229                     continue
    230                 data = arg
    231                 msg = self.data.makechat(data, self.name)
    232                 csock.sendto(msg, address)
    233         csock.close()
    234     def start(self):
    235         self.back.setDaemon(True)
    236         self.back.start()
    237         self.listen.setDaemon(True)
    238         self.listen.start()
    239         self.chatting()
    240         self.back.stop()
    241         self.listen.stop()
    242         sys.exit()
    243 
    244 usermutex = threading.Lock()
    245 outmutex = threading.Lock()
    246 #控制status on和off的情况
    247 anoun = 1
    248 s = Start()
    249 s.start()
  • 相关阅读:
    UML类图与类的关系详解
    hadoop中的Partition
    几种排序
    poj 1006
    Hadoop namenode无法启动
    String中intern的方法
    java
    模板方法模式
    里氏替换原则
    按字节数截取字符串
  • 原文地址:https://www.cnblogs.com/kevince/p/3941728.html
Copyright © 2011-2022 走看看