最近上计算机网络课程,老师给的一个任务,自学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填一样就可以
过几天放上所有源码及工程文件