最近上计算机网络课程,老师给的一个任务,自学python和socket套接字完成一个带GUI界面的实时聊天程序,自己鼓捣了几天算是基本实现了功能,也借鉴了其他博主的一些经验,对于一个只学过c的非cs专业的学生还是有点难度,有很多坑,现在把代码放上来给其他同学一个参考
下面是服务器的py程序,GUI 库使用的是python自带tkinter,可以直接运行,环境是python3.7,初学python,单纯为了实现功能堆代码,还请大佬莫笑=_=
#!/usr/bin/env python
# -*- coding:utf-8 -*-
'''
'by chao'
’936685468@qq.com‘
'服务器程序'
'''
import os, sys
import socket
import threading
import tkinter
import datetime
import time
from tkinter import scrolledtext
from tkinter import messagebox
try:
from tkinter import *
except ImportError: # Python 2.x
PythonVersion = 2
from Tkinter import *
from tkFont import Font
from ttk import *
from tkMessageBox import *
else: # Python 3.x
PythonVersion = 3
from tkinter.font import Font
from tkinter.ttk import *
from tkinter.messagebox import *
gComps = {}
sock = None
num=0
top = Tk()
top.title('TCP服务器 By超')
top.geometry('484x475')
top.resizable(0, 0)
gComps['top'] = top
nowTime = datetime.datetime.now().strftime('%H:%M:%S')
def Cconnect_Cmd(event=None):
s = threading.Thread(target=start)
s.start()
textstatus.delete(0, END)
textstatus.insert(tkinter.INSERT, '%s:等待连接...' % nowTime)
def start():
global sock
ip = textipVar.get()
port = textportVar.get()
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
soc.bind((ip, int(port)))
soc.listen(10)
while 1:
global num
ck, ca = soc.accept()
num=num+1
textstatus.delete(0, END)
textstatus.insert(tkinter.INSERT, '%s:客户端第%d次连接' % (nowTime,num) )
sock = ck
t = threading.Thread(target=recmsg, args=(ck, ca))
t.start()
def recmsg(ck, ca):
while 1:
msgrec = ck.recv(1024)
textrec.see(END)
textrec.insert(tkinter.INSERT, '%s<<收到:%s' % (nowTime, msgrec.decode("utf-8")))
def Csend_Cmd(event=None):
msgsend = textsend.get("0.0", "end")
sock.send(msgsend.encode("utf-8"))
textrec.insert(tkinter.INSERT, '%s>>发送:%s' % (nowTime, msgsend))
textrec.see(END)
textsend.delete('1.0', 'end')
def Cclosed_Cmd(event=None):
sock.send('对方关闭了连接\n'.encode("utf-8"))
sock.close()
textstatus.delete(0, END)
textstatus.insert(tkinter.INSERT, '%s:连接关闭,等待下次连接...' % nowTime)
def Cquit_Cmd(event=None):
sys.exit()
def Command1_Cmd(event=None):
messagebox.showinfo(title='关于', message='T C P 服 务 器 ')
style = Style()
gComps['style'] = style
style.configure('Cquit.TButton', font=('宋体', 10))
Cquit = Button(top, text='退出', command=Cquit_Cmd, style='Cquit.TButton')
Cquit.place(relx=0.38, rely=0.893, relwidth=0.25, relheight=0.053)
gComps['Cquit'] = Cquit
style.configure('Csend.TButton', font=('宋体', 10))
Csend = Button(top, text='发送', command=Csend_Cmd, style='Csend.TButton')
Csend.place(relx=0.645, rely=0.758, relwidth=0.2, relheight=0.053)
gComps['Csend'] = Csend
textstatusVar = StringVar(value='')
textstatus = Entry(top, textvariable=textstatusVar, font=('宋体', 10))
textstatus.place(relx=0.132, rely=0.269, relwidth=0.729, relheight=0.069)
gComps['textstatus'] = textstatus
gComps['textstatusVar'] = textstatusVar
textsendVar = StringVar(value='')
textsend = Text(top, font=('宋体', 9))
textsend.place(relx=0.545, rely=0.387, relwidth=0.382, relheight=0.322)
gComps['textsend'] = textsend
gComps['textsendVar'] = textsendVar
textrecVar = StringVar(value='')
textrec = Text(top, font=('宋体', 9))
textrec.place(relx=0.083, rely=0.387, relwidth=0.399, relheight=0.44)
gComps['textrec'] = textrec
gComps['textrecVar'] = textrecVar
style.configure('Cclosed.TButton', font=('宋体', 10))
Cclosed = Button(top, text='关闭服务', command=Cclosed_Cmd, style='Cclosed.TButton')
Cclosed.place(relx=0.545, rely=0.152, relwidth=0.2, relheight=0.053)
gComps['Cclosed'] = Cclosed
style.configure('Cconnect.TButton', font=('宋体', 10))
Cconnect = Button(top, text='开启服务', command=Cconnect_Cmd, style='Cconnect.TButton')
Cconnect.place(relx=0.198, rely=0.152, relwidth=0.2, relheight=0.053)
gComps['Cconnect'] = Cconnect
textportVar = StringVar(value='')
textport = Entry(top, textvariable=textportVar, font=('宋体', 10))
textport.place(relx=0.562, rely=0.034, relwidth=0.3, relheight=0.069)
gComps['textport'] = textport
gComps['textportVar'] = textportVar
textipVar = StringVar(value='')
textip = Entry(top, textvariable=textipVar, font=('宋体', 10))
textip.place(relx=0.116, rely=0.034, relwidth=0.3, relheight=0.069)
gComps['textip'] = textip
gComps['textipVar'] = textipVar
style.configure('Label3.TLabel', anchor='w', font=('宋体', 10))
Label3 = Label(top, text='状态', style='Label3.TLabel')
Label3.place(relx=0.05, rely=0.286, relwidth=0.068, relheight=0.053)
gComps['Label3'] = Label3
style.configure('Label2.TLabel', anchor='w', font=('宋体', 10))
Label2 = Label(top, text='端口', style='Label2.TLabel')
Label2.place(relx=0.479, rely=0.051, relwidth=0.068, relheight=0.036)
gComps['Label2'] = Label2
style.configure('Label1.TLabel', anchor='w', font=('宋体', 10))
Label1 = Label(top, text='地址', style='Label1.TLabel')
Label1.place(relx=0.033, rely=0.051, relwidth=0.068, relheight=0.036)
gComps['Label1'] = Label1
scroll = tkinter.Scrollbar()
scroll.place(relx=0.479, rely=0.387, relwidth=0.035, relheight=0.44)
# 将滚动条与文本框关联
scroll.config(command=textrec.yview) # 将文本框关联到滚动条上,滚动条滑动,文本框跟随滑动
textrec.config(yscrollcommand=scroll.set) # 将滚动条关联到文本框
style.configure('Command1.TButton', font=('宋体', 9))
Command1 = Button(top, text='点我点我', command=Command1_Cmd, style='Command1.TButton')
Command1.place(relx=0.777, rely=0.859, relwidth=0.134, relheight=0.103)
gComps['Command1'] = Command1
top.mainloop()
下面是客户端程序的py文件
#!/usr/bin/env python
#-*- coding:utf-8 -*-
'''
'by chao'
’936685468@qq.com‘
'''
import os, sys
import socket
import threading
import tkinter
import datetime
from tkinter import messagebox
try:
from tkinter import *
except ImportError: #Python 2.x
PythonVersion = 2
from Tkinter import *
from tkFont import Font
from ttk import *
from tkMessageBox import *
else: #Python 3.x
PythonVersion = 3
from tkinter.font import Font
from tkinter.ttk import *
from tkinter.messagebox import *
gComps = {}
sock = None
top = Tk()
top.title('TCP客户端 By超')
top.geometry('484x475')
top.resizable(0,0)
gComps['top'] = top
nowTime=datetime.datetime.now().strftime('%H:%M:%S')
def Cconnect_Cmd(event=None):
global sock
ip = textipVar.get()
port = textportVar.get()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, int(port)))
textstatus.delete(0, END)
textstatus.insert(tkinter.INSERT, '%s:连接成功' % nowTime)
sock = s
t = threading.Thread(target=recmsg)
t.start()
def recmsg():
while 1:
msgrec = sock.recv(1024)
textrec.insert(tkinter.INSERT, '%s<<收到:%s' % (nowTime,msgrec.decode("utf-8")))
textrec.see(END)
def Csend_Cmd(event=None):
msgsend = textsend.get("0.0", "end")
sock.send(msgsend.encode("utf-8"))
textrec.insert(tkinter.INSERT, '%s>>发送:%s' % (nowTime, msgsend))
textrec.see(END)
textsend.delete('1.0', 'end')
def Cclosed_Cmd(event=None):
sock.send('对方关闭了连接\n'.encode("utf-8"))
sock.close()
textstatus.delete(0, END)
textstatus.insert(tkinter.INSERT, '%s:连接断开' % nowTime)
def Cquit_Cmd(event=None):
sys.exit()
def Command1_Cmd(event=None):
messagebox.showinfo(title='关于', message='T C P ')
######
style = Style()
gComps['style'] = style
style.configure('Cquit.TButton',font=('宋体',10))
Cquit = Button(top, text='退出', command=Cquit_Cmd, style='Cquit.TButton')
Cquit.place(relx=0.38, rely=0.893, relwidth=0.25, relheight=0.053)
gComps['Cquit'] = Cquit
style.configure('Csend.TButton',font=('宋体',10))
Csend = Button(top, text='发送', command=Csend_Cmd, style='Csend.TButton')
Csend.place(relx=0.645, rely=0.758, relwidth=0.2, relheight=0.053)
gComps['Csend'] = Csend
textstatusVar = StringVar(value='')
textstatus = Entry(top, textvariable=textstatusVar, font=('宋体',10))
textstatus.place(relx=0.132, rely=0.269, relwidth=0.729, relheight=0.069)
gComps['textstatus'] = textstatus
gComps['textstatusVar'] = textstatusVar
textsendVar = StringVar(value='')
textsend = Text(top, font=('宋体',9))
textsend.place(relx=0.545, rely=0.387, relwidth=0.382, relheight=0.322)
gComps['textsend'] = textsend
gComps['textsendVar'] = textsendVar
textrecVar = StringVar(value='')
textrec = Text(top, font=('宋体',9))
textrec.place(relx=0.083, rely=0.387, relwidth=0.399, relheight=0.44)
gComps['textrec'] = textrec
gComps['textrecVar'] = textrecVar
style.configure('Cclosed.TButton',font=('宋体',10))
Cclosed = Button(top, text='断开连接', command=Cclosed_Cmd, style='Cclosed.TButton')
Cclosed.place(relx=0.545, rely=0.152, relwidth=0.2, relheight=0.053)
gComps['Cclosed'] = Cclosed
style.configure('Cconnect.TButton',font=('宋体',10))
Cconnect = Button(top, text='连接', command=Cconnect_Cmd, style='Cconnect.TButton')
Cconnect.place(relx=0.198, rely=0.152, relwidth=0.2, relheight=0.053)
gComps['Cconnect'] = Cconnect
textportVar = StringVar(value='')
textport = Entry(top, textvariable=textportVar, font=('宋体',10))
textport.place(relx=0.562, rely=0.034, relwidth=0.3, relheight=0.069)
gComps['textport'] = textport
gComps['textportVar'] = textportVar
textipVar = StringVar(value='')
textip = Entry(top, textvariable=textipVar, font=('宋体',10))
textip.place(relx=0.116, rely=0.034, relwidth=0.3, relheight=0.069)
gComps['textip'] = textip
gComps['textipVar'] = textipVar
style.configure('Label3.TLabel',anchor='w', font=('宋体',10))
Label3 = Label(top, text='状态', style='Label3.TLabel')
Label3.place(relx=0.05, rely=0.286, relwidth=0.068, relheight=0.053)
gComps['Label3'] = Label3
style.configure('Label2.TLabel',anchor='w', font=('宋体',10))
Label2 = Label(top, text='端口', style='Label2.TLabel')
Label2.place(relx=0.479, rely=0.051, relwidth=0.068, relheight=0.036)
gComps['Label2'] = Label2
style.configure('Label1.TLabel',anchor='w', font=('宋体',10))
Label1 = Label(top, text='地址', style='Label1.TLabel')
Label1.place(relx=0.033, rely=0.051, relwidth=0.068, relheight=0.036)
gComps['Label1'] = Label1
scroll = tkinter.Scrollbar()
scroll.place(relx=0.479, rely=0.387, relwidth=0.035, relheight=0.44)
# 将滚动条与文本框关联
scroll.config(command=textrec.yview) # 将文本框关联到滚动条上,滚动条滑动,文本框跟随滑动
textrec.config(yscrollcommand=scroll.set) # 将滚动条关联到文本框
style.configure('Command1.TButton', font=('宋体', 9))
Command1 = Button(top, text='点我点我', command=Command1_Cmd, style='Command1.TButton')
Command1.place(relx=0.777, rely=0.859, relwidth=0.134, relheight=0.103)
gComps['Command1'] = Command1
top.mainloop()
需要注意的是,在同一局域网上的两台电脑使用这个软件连接的话,服务器的地址要写所在计算机的本机的ip,客户端要填写服务器计算机的ip,另外要先试一试两台电脑能不能互相ping通。
如果是在同一台电脑上运行,那么这两个程序ip填一样就可以
过几天放上所有源码及工程文件