使用python自带的Tkinter实现了一个类似于QQ的客户端,但是需要知道对方的IP地址才能连通通信(在局域网内实验成功),对于诸如什么 NAT等问题也没有考虑过,而且,界面简单,很多地方没有仔细琢磨,字体非常的小,都快看不清了(使用的默认字体)。程序中使用了线程机制。具体代码如 下:
#coding: UTF-8
from Tkinter import *
from ScrolledText import *
import socket
import threading
import Queue
import time
__host__ = ""
__port__ = 52431
root = Tk()
root.title("Comm Demo")
root.wm_resizable(False, False) #can not resize
#定义全局的socket变量
s_conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s_host = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#定义全局连接变量
connection = None
#
hostname = socket.gethostname().encode("UTF-8")
#
def connect ():
host = ipaddr.get()
port = int(portaddr.get())
print host, port
s_conn.connect((host, port))
s_conn.send(hostname)
def send ():
content = inputtext.get("1.0", END)
print len(content)
inputtext.delete("1.0", END)
if len(content) == 1:
return
else:
localtime = time.ctime()
content = localtime + " : /n" + content.encode("UTF-8")
showtext.insert(END, hostname + " " + content)
s_conn.send(content)
#
frame = Frame(root)
Label(frame, text = "IP Addr: ").pack(side = LEFT)
ipaddr = Entry(frame)
ipaddr.pack(side = LEFT, fill = BOTH, expand = 1)
ipaddr.insert(END, __host__)
Label(frame, text = " Port: ").pack(side = LEFT)
portaddr = Entry(frame, width = 6)
portaddr.pack(side = LEFT)
portaddr.insert(END, "%s" % __port__)
okbtn = Button(frame, text = "Connect", command = connect)
okbtn.pack(side = RIGHT)
frame.pack(side = TOP)
#
frame = Frame(root)
showtext = ScrolledText(frame, width = 100, height = 40)
showtext.pack(side = TOP, fill = BOTH)
frame.pack(side = TOP)
#
frame = Frame(root)
inputtext = ScrolledText(frame, width = 80, height = 5)
inputtext.pack(side = LEFT, fill = BOTH)
sendbtn = Button(frame, text = "Send", command = send)
sendbtn.pack(side = RIGHT, fill = BOTH)
frame.pack(side = BOTTOM)
#
#
def buildhost (queue):
s_host.bind((__host__, __port__))
s_host.listen(1)
connection, addr = s_host.accept()
addr = "( %s:%d )" % (addr[0], addr[1])
showtext.insert(END, "[ " + addr)
showtext.insert(END, u" 已经连接上]/n")
recvdata = False
remotehostname = None
while True:
data = connection.recv(256)
if not data:
time.sleep(2)
continue
if not recvdata:
remotehostname = data.decode("UTF-8")
recvdata = True
else:
data = data.decode("UTF-8")
showtext.insert(END, remotehostname + " ")
showtext.insert(END, "%s" % data)#这里不需要加一个/n就已经能够换行了
showtext.see(END)
s_host.close()
def init (queue):
root.mainloop()
queue = Queue.Queue(0)
t = threading.Thread(target=buildhost, args = (queue,))
t.setDaemon(True)
t.start()
#
root.mainloop()
运行起来的界面如下图: