Vtalk局域网聊天室 基于Python

news/2024/11/17 3:54:38/

服务端:

#作者:吴子豪
#服务器启动程序
import os
import threading,socket,time,datetime,sys#每次运行都清空日志
saveservermsg=open("#Serverlog.hst", 'w')
saveservermsg.close()#服务器配置
host=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
hostname=socket.gethostname()#port=int(input("SYSTEM: Port(1024~65535):"))
port=23817host.bind((hostname,port))#获取客户端个数
num_of_clients=int(input("SYSTEM: Clients(total):"))
num_of_clients+=1
print("SYSTEM: Server Running...")
#服务器同时监听客户端总数
host.listen(num_of_clients)
#创建客户端预估总数列表
clients=list(range(0,num_of_clients))#将range object转换为列表以修改其中元素
#实际在线客户端列表
clientol=[]#定义服务器行为
addr={None:None}
Cli={None:None}#客户端编号字典print("SYSTEM: \"dc\" To Shut Down Server")
boole=1#若boole为1则服务器保持运行#全局变量 用于统一各线程
glo=globals()#将服务器log重定向写入文件
saveservermsg=open("#Serverlog.hst", 'a')#将日志输入到文件def serverclos():#控制服务器关闭while glo["boole"]:cmd=str(input())if cmd=="dc":repo=open("#ServerReport.err",'w')sys.stderr=repohost.close()print("SYSTEM: Server Is Closing Soon.......")saveservermsg.write("SYSTEM: Server has been closed\n")saveservermsg.close()#关闭文件glo["boole"]=0else:pass
servcls=threading.Thread(target=serverclos,args=())#该线程负责获取服务器命令def printtime():#打印当前系统时间time.sleep(3)while glo["boole"]:now_time = datetime.datetime.now().strftime('%D %T %A')saveservermsg.write("\n")saveservermsg.write(now_time)saveservermsg.write("\n")saveservermsg.write("-------------------------\n")print(now_time)time.sleep(30)
pritime=threading.Thread(target=printtime,args=())#该线程负责打印时间 30秒一次def connect(N):#主线程while glo["boole"]:Cli[N],addr[N]=host.accept()#等待与客户端建立连接clientol.append(N)print('C_SYSTEM: User <{}> online,using port:{}'.format(addr[N][0],addr[N][1]))#获取第N号客户端的ipv4和端口#告知其他在线客户端 此客户端上线for index in clientol:if index != N:if Cli[index]!=None:onlinemsg="Server: User<{}> Online".format(addr[N][0])Cli[index].send(onlinemsg.encode())else:passelse:pass#同步到日志saveservermsg.write('SYSTEM: User <{}> online,using port:{}\n'.format(addr[N][0],addr[N][1]))Cli[N].send(b"Server:Client Connected")#对客户端进行初次连接反馈while glo["boole"]:#获取第N号客户端发送的多条讯息try:#若客户端被强制关闭则自动销毁套接字msg=Cli[N].recv(4096)if msg == '':passelif msg == b"><01~>0":#检查客户端是否在线print('SYSTEM: Client No.{}-<{}> still online'.format(N,addr[N][0]))try:saveservermsg.write('SYSTEM: Client No.{}-<{}> still online\n'.format(N,addr[N][0]))except:passelif msg == b"Server Is Under Listening":print("ServerSupport: " + msg.decode())saveservermsg.write("ServerSupport: " + msg.decode())saveservermsg.write(msg.decode())saveservermsg.write("\n")elif msg == b"dc":#客户端下线print('C_SYSTEM: User <{}> offline'.format(addr[N][0]))#以C_开头表示这是可以传输给客户端的信息#反馈给客户端 让客户端接收消息线程停止Cli[N].send(b"stop_client-True>")#告知所有其他客户端该客户端下线for index in clientol:if index != N:if Cli[index] != None:onlinemsg = "Server: User<{}> Offline".format(addr[N][0])Cli[index].send(onlinemsg.encode())else:passelse:pass#储存到日志saveservermsg.write('C_SYSTEM: User <{}> offline\n'.format(addr[N][0]))#删除该客户端编号clientol[int(N)]=None#断开此客户端连接Cli[N].close()#清空客户端信息Cli[N]=Noneaddr[N]=None#变为空套接字,等待下一个客户端的接入breakelse:print("Client No.{}-<{}>:".format(N,addr[N][0]),msg.decode())#接收第N号客户端的讯息#将信息同步到所有客户端for index in clientol:if Cli[index] != None:onlinemsg = "Client No.{}-<{}>:".format(N,addr[N][0])#Cli[index].send(onlinemsg.encode()+msg)#控制台版本Cli[index].send('{}'.format(addr[N][0]).encode()+msg)#GUI版本else:pass#将信息储存到日志saveservermsg.write("Client No.{}-<{}>:".format(N,addr[N][0]))saveservermsg.write(msg.decode())saveservermsg.write("\n")#客户端非正常关闭except:print("SYSTEM: Client No.{}-<{}> unexpected lost connection".format(N,addr[N][0]))try:saveservermsg.write("SYSTEM: Client No.{}-<{}> unexpected lost connection\n".format(N,addr[N][0]))except:pass# 告知所有其他客户端该客户端下线for index in clientol:if index != N:if Cli[index] != None:onlinemsg = "Server: User<{}> Offline".format(addr[N][0])Cli[index].send(onlinemsg.encode())else:passelse:pass# 储存到日志saveservermsg.write('C_SYSTEM: User <{}> offline\n'.format(addr[N][0]))# 删除该客户端编号clientol[int(N)] = None# 关闭此客户端套接字Cli[N].close()# 清空客户端信息Cli[N] = Noneaddr[N] = None# 变为空套接字,等待下一个客户端的接入break#根据客户端数量创建线程列表
thr=[]
for n in clients:thr.append(threading.Thread(target=connect,args=(str(n),)))#对空线程列表添加线程#服务器开始运行
for n in clients:thr[n].start()#thr[n].join()
pritime.start()
servcls.start()

客户端(CLI):

#作者:吴子豪
import socket,tkinter,threading,sys,time
#指定目标服务器
client1=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
hostname="V-PIG"#服务器名#port=int(input("SYSTEM: Port(1024~65535):"))
port=23817#发起连接申请
client1.connect_ex((hostname,port))print("Server: Input \"dc\" to Disconnect")g=globals()
ckeck=1
msg=''#接收服务器消息
def recvmsg():while g['check']:try:msgs=client1.recv(1024)if msgs == '':pass#客户端结束时接收消息线程需要服务器的反馈来结束elif msgs == b"stop_client-True>":breakelse:print(msgs.decode())except:client1.close()g["check"]=0print("SYSTEM: Lost Connection")print("SYSTEM: Press \"Enter\" to exit")time.sleep(5)break
revcmsgs=threading.Thread(target=recvmsg,args=())#该线程负责收取服务器消息def check():while g['check']:time.sleep(10)try:client1.send(b"><01~>0")if g["msg"] =="dc":breakexcept:pass
ckline=threading.Thread(target=check,args=())#向服务器反馈连接情况def sendmsg():#向服务器发送消息while g["check"]:try:g["msg"]=input("")except:passtry:if g["msg"] == "dc":client1.send(msg.encode())client1.close()g["check"] = 0print("SYSTEM: Client offline")time.sleep(5)breakelse:client1.send(msg.encode())except:pass
sdmsg = threading.Thread(target=sendmsg, args=())revcmsgs.start()
sdmsg.start()
ckline.start()

客户端(GUI):

客户端的窗口图标文件要保存在和客户端同路径下的ico路径中

客户端图标:     

#作者:吴子豪
import time
import tkinter as tk#创建窗口对象
top=tk.Tk()
#窗口命名为app名
top.title("Vtalk Beta(Offline)")
#添加窗口图标 可注释
top.iconphoto(True, tk.PhotoImage(file='ico/microvtalk.png'))
top.geometry("1200x521")
top.configure(bg='black')
top.resizable(width=False, height=False)#创建文本输入框
inputmsg = tk.Entry(top,width=104,bg='black',fg='white',highlightcolor='green',highlightthickness=2,font=(11))
inputmsg.grid(column=1,row=2)#创建文本框滚动条
#scroll=tk.Scrollbar(top)
#scroll.grid(column=2,row=1)#创建文本框
tip = tk.Text(bg="black",#anchor='nw',cursor='circle',font=(8),fg='white',height=20,width=104,#justify="left",relief='sunken',#text='',#yscrollcommand=scroll.set,)
#scroll.config(command = tip.yview)#用户名列表
tip.grid(column=1,row=1)
onlines = tk.Text(bg="black",cursor='arrow',font=(5),fg='green',height=20,width=15,relief='flat',)
onlines.grid(column=2,row=1)#上面是图形界面#程序主体--客户端import socket,threading,sys
#指定目标服务器
client1=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
gethostname=open("HOST_NAME.txt",'r')
hostname=gethostname.read()
gethostname.close()#hostname="V-PIG"#服务器名
#hostname="Y2K"#服务器名#port=int(input("SYSTEM: Port(1024~65535):"))
port=23817#固定端口g=globals()
ckeck=1
msg=''
username=''
#锁定所有text栏目
onlines.configure(state='disabled')
tip.configure(state='disabled')#接收服务器消息
def recvmsg():while g['check']:try:msgs=client1.recv(1024)if msgs == '':passelif msgs == b"Server:Client Connected":top.title("Vtalk Beta(Online)")onlines.configure(state='normal')onlines.insert(tk.END, 'Vtalk '+'On' + '\n\n')onlines.update()onlines.configure(state='disabled')#客户端结束时接收消息线程需要服务器的反馈来结束elif msgs == b"stop_client-True>":break#输出在线用户动态elif msgs.decode()[:12] == "Server: User":onlines.configure(state='normal')onlines.insert(tk.END, msgs.decode()[12:]+ '\n\n')onlines.update()onlines.configure(state='disabled')else:output=msgs.decode()tip.configure(state='normal')tip.insert(tk.END, output + '\n')tip.update()tip.configure(state='disabled')except:top.title("Vtalk Beta(Offline)")onlines.configure(state='normal')onlines.insert(tk.END, 'Bad challenge'+ '\n\n')onlines.update()onlines.configure(state='disabled')break
revcmsgs=threading.Thread(target=recvmsg,args=())#该线程负责收取服务器消息def check():while g['check']:time.sleep(10)try:client1.send(b"><01~>0")if g["msg"] =="dc":breakexcept:pass
ckline=threading.Thread(target=check,args=())#向服务器反馈连接情况def gettext(self):text = inputmsg.get()try:g["msg"]=textexcept:passtry:client1.send(b'('+g["username"].encode()+b'): '+text.encode())except:onlines.configure(state='normal')onlines.insert(tk.END, 'Bad challenge' + '\n\n')onlines.update()onlines.configure(state='disabled')inputmsg.delete(0, 'end')inputmsg.update()
#回车发送消息
inputmsg.bind('<Return>',gettext)#创建下方信息栏
info = tk.Text(bg='black',fg='green',font=(2),width=104,height=2,relief='flat',)
info.grid(column=1,row=3)def geton():g['username'] = name.get()#获取用户名# 更新信息栏info.configure(state='normal')info.delete(1.0, 5.10)info.insert(tk.END, 'Current Client Host: {}'.format(socket.gethostname()))info.insert(tk.END, ' ' * 45 + 'Current Username: ' + '\"' + g['username'] + '\" ')info.insert(tk.END, '\nVtalk Beta Version By Vortex' + ' ' * 43 + 'Contact Me:2310108909@qq.com')info.update()info.configure(state='disabled')# 发起连接申请'''client1.connect_ex((hostname, port))revcmsgs.start()ckline.start()'''def getoff():try:client1.send(b'dc')client1.close()g["check"] = 0onlines.configure(state='normal')onlines.insert(tk.END, 'Vtalk ' + 'Off' + '\n\n')onlines.update()onlines.configure(state='disabled')top.destroy()try:exit()except:passexcept:g["check"] = 0onlines.configure(state='normal')onlines.insert(tk.END, 'Vtalk ' + 'Off' + '\n\n')onlines.update()onlines.configure(state='disabled')top.destroy()try:exit()except:pass#创建用于下线的按钮
off = tk.Button()
off.config(text='Quit',fg='black',bg='green',width=14,#font=('ROGFonts-Regular',11),height=2,font=(11),command=getoff)
off.grid(column=2,row=3)
#创建用于重命名的按钮
on = tk.Button()
on.config(text='Rename',fg='black',bg='green',width=14,#font=('ROGFonts-Regular',11),font=(11),command=geton)
on.grid(column=2,row=2)
#用户名框
name = tk.Entry(bg="black",font=(11),fg='white',#height=2,width=14,relief='flat',highlightcolor='green',highlightthickness=2,)
name.grid(column=2,row=4)#生成随机用户名
import random
name.insert(tk.END, "User.{}".format(random.randint(0,1000)))
name.update()
g['username'] = name.get()#获取默认用户名
#更新信息栏
info.configure(state='normal')
info.delete(1.0,5.10)
info.insert(tk.END, 'Current Client Host: {}'.format(socket.gethostname()))
info.insert(tk.END, ' '*45+'Current Username: ' + '\"' + g['username'] + '\" ')
info.insert(tk.END, '\nVtalk Beta Version By Vortex'+' '*43+'Contact Me:2310108909@qq.com')
info.update()
info.configure(state='disabled')
#自动连接
try:client1.connect_ex((hostname, port))
except:pass
revcmsgs.start()
ckline.start()
#运行窗口
tk.mainloop()

客户端需要读入一个HOST_NAME.txt文件来获取主机名

获取服务主机:

//作者:吴子豪
#include<iostream>
#include<fstream>
#include<Windows.h> 
#include<conio.h>
using namespace std;
int main()
{ofstream in;in.open("HOST_NAME.txt");in<<" ";in.close();ofstream out;string hostname=" ";cout<<"-----------------------Vtalk-----------------------\n请输入服务主机名\n服务主机:";cin>>hostname;out.open("HOST_NAME.txt");out<<hostname;out.close();cout<<"<按任意键继续>";getch();
}


http://www.ppmy.cn/news/933713.html

相关文章

Web聊天室

目录 一&#xff0c;简介 二&#xff0c;开发环境 三&#xff0c;涉及的技术 四&#xff0c;主要功能 1.注册功能 2.登录功能 3.异地登陆&#xff08;第一次登录网页会被强制退出&#xff09; 4.发送消息 5.接收消息 6.注销登录 五&#xff0c;准备工作 1.引入开发…

局域网聊天系统-Java

这个局域网聊天系统&#xff0c;是为了能够在一个没有连接到intent的局域网中&#xff0c;进行聊天的一个程序。本程序包括服务器和客户机两部分&#xff0c;可以实现多人聊天和两个人私聊的一个工具。 开发语言&#xff1a;Java&#xff0c;开发工具&#xff1a;eclipse。 客户…

Java实现局域网聊天软件分享

前言 翻翻u盘里面的东西,发现了自己以前实现的局域网聊天软件。这里共享出来给各位学习 Java的童鞋。对知识的渴望源自于人的内心&#xff0c;对知识的分享也源自于人的本性。 功能罗列 啥功能笔者就不去重新实践了&#xff0c;简单的罗列下功能列表&#xff1a; 1. 消息发送&a…

Java实现多线程局域网聊天室

Java多线程局域网聊天室 局域网聊天室1.TCP2.套接字3.C/S架构4.多线程5.服务器客户端 局域网聊天室 在学习了一个学期的java以后&#xff0c;觉得java真是博大精深&#xff0c;彻底放弃了因为c而轻视java的心态&#xff0c;搞了一个多线程的聊天室&#xff0c;熟悉了一下服务器…

局域网内互发消息

主机相互发送消息 背景 本学期的计算机网络课非常有意思&#xff0c;它与我们的生活息息相关&#xff0c;曾经我也为电脑发生的网络问题而困惑&#xff0c;总是没有根据的瞎尝试来试图解决问题。但是在老师的一些简单指导之后&#xff0c;有了一个基本的ip之间通信以及局域网…

基于java编写局域网多人聊天室

基于java编写局域网多人聊天室 由于需要制作网络计算机网络课程设计&#xff0c;并且不想搞网络布线或者局域网路由器配置等等这种完全搞不懂的东西&#xff0c;最后决定使用socket基于java编写一个局域网聊天室&#xff1a; 关于socket以及网络编程的相关知识详见我另一篇文…

Java实战_局域网多人聊天室

由于需要制作网络计算机网络课程设计&#xff0c;并且不想搞网络布线或者局域网路由器配置等等这种完全搞不懂的东西&#xff0c;最后决定使用socket基于java编写一个局域网聊天室&#xff1a; 关于socket以及网络编程的相关知识详见我另一篇文章:Java基于socket编程 程序基于…

JAVA实现聊天室(局域网)

JAVA用局域网实现聊天室 类和接口 Server类&#xff08;服务器端&#xff09; package Test;import java.io.IOException; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket;public class Server {private static final int SERVER_PORT30…