【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 = 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()
时间: 2024-08-13 15:15:30

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

Linux命令行下如何终止当前程序?

Linux命令行下如何终止当前程序? 快捷键: Ctrl+c 在命令行下起着终止当前执行程序的作用, Ctrl+d 相当于exit命令,退出当前shell Ctrl+s 挂起当前shell(保护作用很明显哦) Ctrl+q 解冻挂起的shell再不行就重新连接打开一个终端,reboot linux 或 kill 相关进程. 原文地址:https://www.cnblogs.com/pythonClub/p/10914338.html

[兴趣使然]用python在命令行下画jandan像素超载鸡

下午刷煎蛋的时候看到 Dthalo 蛋友发的系列像素超载鸡,就想自己试试用python脚本画一个,老男孩视频里的作业真没兴趣,弄不好吧没意思,往好了写,自己控制不好,能力不够. 所以还是找自己有兴趣的先练练手,先实现,然后慢慢解耦. *1.因为颜色有限,给超载鸡染了绿毛. 2.用字符串的join方法尽量减少字符显示宽度的影响. 3.目前用命令行下运行有效,以后应该改为os.system方法运行. 4.试过了字符串的center方法,但是该方法使用的填充字符必须是一个字符,字符串不行. 5.用的 

Java初学者:java是如何在命令行下编译运行程序的

我们上文书说到,我们首先安装Java,然后设置Java环境,然后编译运行了一个简单的Java程序,在命令行模式下显示了一个“Hello baby”.那么,为什么呢?发生了什么呢? 首先,下载安装Java就不用问为什么了对吧?所谓巧妇难为无米之炊,没有Java却想用,这不可能的. 其次,为什么我们要那样设置Java的运行环境呢? 因为,目前为止,我只是想在命令行下编译运行java程序,这样一来,你就需要让命令行模式识别java的命令.而命令行下能自动识别的命令,必须我们手动的把命令的路径添加进去.

windows安装使用python、环境设置、多python版本的切换、pyserial与多版本python安装、windows命令行下切换目录

1.windows下安装python 官网下载安装即可 2.安装后的环境设置 我的电脑--属性--高级--设置path的地方添加python安装目录,如C:\Python27;C:\Python33 3.多版本的切换三种方法: 1)修改C:\Python27;C:\Python33内python.exe为python2.7.exe.python3.3.exe,即可区别开来 2)path路径中去除不用的,保留要用的 3)切换到想使用版本的python.exe目录下使用python解释器 4.下载好

Python安装后在CMD命令行下出现“应用程序无法启动.............”问题

问题存在之一:系统是刚刚重做的精简版服务器系统(阉割版) AN就是在阿里云上刚开的Windows Server 2008 系统上碰到的  吓尿了都 症状:            正常安装python环境后 进入cmd命令行中,执行python就报错,报错的大概内容就是 “应用程序无法启动....因为并行配置不正确...请执行....exe文件”  PS:卧槽,记不清了, 错误截图 也找不到了 下药:          1.面对CMD命令行报错,代开事件查看器 可以通过控制面板打开,也可以在cmd

如何在命令行下设置默认的Python版本?(已解决)

2018年7月3日 北京实时天气:热,比前几天好点,扇着风扇很舒服. 研究Python多版本共存问题:Windows7 64位系统,同时安装了Python2.7及Python3.5,如何在命令行下设置默认的版本? This is a big problem. 今天找到了办法: 可以通过设置环境变量的办法解决,哪一个设置在前面,哪一个版本就是命令行下的默认版本. 很神奇,是不是?[中国赞] 原文地址:http://blog.51cto.com/shbiao05/2135798

Python 标准库 -> Getpass 模块 -> 命令行下输入密码的方法.

getpass 模块 getpass 模块提供了平台无关的在命令行下输入密码的方法. getpass(prompt) 会显示提示字符串, 关闭键盘的屏幕反馈, 然后读取密码. 如果提示参数省略, 那么它将打印出 "Password:". getuser() 获得当前用户名, 如果可能的话. 使用 getpass 模块 1 import getpass 2 3 usr = getpass.getuser() 4 pwd = getpass.getpass("enter pass

python 解析命令行

原文 http://python.jobbole.com/87014 python解析命令行 2016/12/13 · 基础知识 · 命令行 分享到:0 原文出处: 顾慎为 getopt:和C中的getopt()等价.optparse:2.7后已不推荐使用.argparse:基于optparse的新库.docopt:根据文档描述,自动生成.另一份参考文档:docopt. 更详细的内容可参考上述文档. getopt 若对C的getopt()函数不熟悉,或者倾向于使用较少的代码,或者需要对帮助信息和

Linux命令行下的快捷键

1. 命令行下的快捷键 经常在命令行下工作的同志们,可能用的最多的就是两个上下键,主要用来调出历史命令:使用左右箭头使光标向后或向前移动以修改上次使用过的命令.其实这样做效率并不是很高,有了快捷键可以让我们的效率有所提高,而且看起来还更专业.更加Awesome.更加Geek.掌握了这些快捷键,我们可以做到手不离主键盘区域,完全可以忽略掉键盘上的四个可爱的箭头.当我们熟练之后,会越发喜欢这种方式. 1.1 常用快捷键介绍 下面介绍一些作者在命令行下经常使用的快捷键,这些快捷键在Emacs下面是有同