基础聊天室的实现,实现同局域网的聊天,有详细代码

news/2024/11/17 5:32:56/

**

聊天室的实现,基本步骤解析

**
总体思想结构
1.建立服务器端,服务器端不需要界面
建立一个包为服务器包 serve
包内应该有服务器的主方法用来启动服务器,和一个用来接收客户端消息并且转发给所有的客户端的线程类 服务器给所有客户端发消息的线程
2.建立客户端,有界面
建立一个包为客户端包 cient
包内应该有客户端的界面类,可以单独的运行(即有主方法),并且需要一个向服务器发送消息的线程类和一个发送消息的方法,主体大致结构如下
在这里插入图片描述
下面进行更深一步的的讲解
客户端
CientUI.java类:
构建自己喜欢的swing界面;
为按钮添加监听器;(主要逻辑代码)
可以有一个连接服务器的方法

package cient;import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.Socket;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;/*** 客户端的主界面类* @author VastWu**/
public class CientUI {private Socket socket;public SendUtil su;public static void main(String[] args) {CientUI cientUI=new CientUI();cientUI.init();}//连接服务器的方法public Socket connection() {try {//尝试连接服务器Socket socket=new Socket("127.0.0.1", 100);return socket;} catch (Exception e) {e.printStackTrace();}return null;}public void init() {JFrame jframe=new JFrame("714皇家赌场");jframe.setSize(700, 500);jframe.setDefaultCloseOperation(3);jframe.setLayout(null);//设置界面居中jframe.setLocationRelativeTo(null);//设置最大化按钮不可用jframe.setResizable(false);//历史消息框、并且添加滚动条JTextArea historyMsg=new JTextArea();JScrollPane jsp=new JScrollPane(historyMsg);jsp.setBounds(5, 25, 685, 300);historyMsg.setEditable(false);jframe.add(jsp);//发送消息框JTextArea sendMsg=new JTextArea();JScrollPane jsp2=new JScrollPane(sendMsg);jsp2.setBounds(5, 325, 600, 140);jframe.add(jsp2);//按钮JButton sendBut=new JButton("发送");JButton clearBut=new JButton("清空");JButton connectBut=new JButton("连接服务器");sendBut.setBounds(605, 364, 84, 100);clearBut.setBounds(605, 325, 84, 40);connectBut.setBounds(5, 1, 150, 22);jframe.add(connectBut);jframe.add(sendBut);jframe.add(clearBut);//给按钮添加监听器ActionListener al=new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String command=e.getActionCommand();switch (command) {case "发送":if(socket!=null) {String msg=sendMsg.getText().trim();sendMsg.setText("");historyMsg.append("我说:"+msg+"\r\n");//调用方法发送出去su.send(msg);}break;case "清空":sendMsg.setText("");break;case "连接服务器":socket=CientUI.this.connection();if(socket==null) {JOptionPane.showMessageDialog(null, "连接失败,请检查网络或重新连接!");}else {connectBut.setText("已连接服务器");JOptionPane.showMessageDialog(null, "连接成功!");//启动线程并且给服务器发送消息ReceiveThread rt=new ReceiveThread(socket, historyMsg);rt.start();su=new SendUtil(socket);}break;default:break;}}};connectBut.addActionListener(al);sendBut.addActionListener(al);clearBut.addActionListener(al);jframe.setVisible(true);}
}

ReceiveThread.java类:
接收服务器信息的线程类并且把消息加到界面中

package cient;import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;import javax.swing.JTextArea;/*** 接收来自服务器的线程类* @author VastWu**/
public class ReceiveThread extends Thread{private Socket socket;private JTextArea historyMsg;public ReceiveThread(Socket socket,JTextArea historyMsg) {this.socket=socket;this.historyMsg=historyMsg;}@Overridepublic void run() {try {InputStream ips=socket.getInputStream();InputStreamReader isr=new InputStreamReader(ips);BufferedReader br=new BufferedReader(isr);while(true) {String msg=br.readLine();historyMsg.append(msg+"\r\n");}} catch (Exception e) {e.printStackTrace();}}
}

SendUtil类
客户端发送消息的类

package cient;import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;/*** 发送消息的类* @author VastWu**/
public class SendUtil {private Socket socket;private BufferedWriter bw;private String add;public SendUtil(Socket socket) {this.socket=socket;try {OutputStream ops=socket.getOutputStream();OutputStreamWriter osw=new OutputStreamWriter(ops);bw=new BufferedWriter(osw);add=socket.getLocalSocketAddress().toString();} catch (Exception e) {e.printStackTrace();}	}public void send(String msg) {try {bw.write(add+"说:"+msg+"\r\n");bw.flush();} catch (IOException e) {e.printStackTrace();}}
}

服务端
Serve.java类
启动一个服务器的类

package serve;import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;/*** 服务器端* @author VastWu**/
public class Serve {//声明一个集合用于储存socket对象public static ArrayList<Socket> socketList=new ArrayList<Socket>();//直接主方法以启动服务器public static void main(String[] args) throws Exception {//使用一个服务端套接字建立一个端口ServerSocket serverSocket=new ServerSocket(100);System.out.println("服务器开启成功,正在等待连接。。。");SendAllThread sat=new SendAllThread();sat.start();//为了使socket对象不被覆盖这里使用while死循环对socket进行储存while(true) {//等待连接Socket socket=serverSocket.accept();//连接成功后存入集合内socketList.add(socket);//得到客户端的地址String address=socket.getRemoteSocketAddress().toString();//连接成功后控制台提示连接成功System.out.println(address+"连接上来了");//启动转发线程TurnSendThread tst=new TurnSendThread(socket);tst.start();//启动通知线程TellThread tt=new TellThread(socket);tt.start();}}
}

SendAllThread.java类
服务器主动给服务器发信息的线程类

package serve;import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;/*** 给所有客户端发消息的线程类* @author VastWu**/
public class SendAllThread extends Thread{@Overridepublic void run() {try {//服务器控制台发送消息Scanner scan=new Scanner(System.in);//因为要发多条消息,所以用死循环while(true) {//接收输入的一行消息String msg=scan.nextLine();//使用输出流进行处理,并且需要向所有用户发消息所以需要对集合进行循环发送for(Socket socket:Serve.socketList) {OutputStream ops=socket.getOutputStream();OutputStreamWriter osw=new OutputStreamWriter(ops);BufferedWriter bw=new BufferedWriter(osw);bw.write("服务器说:"+msg+"\n");bw.flush();}}} catch (IOException e) {e.printStackTrace();}}
}

TurnSendThread.java类
转发消息的线程类,即把客服端发过来的信息转发给所有的客户端

package serve;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;/*** 转发客服端发送过来的消息的线程类* @author VastWu**/
public class TurnSendThread extends Thread{private Socket socket;private String address;//先使用构造方法把socket传过来public TurnSendThread(Socket socket) {this.socket=socket;//客户端的地址address=socket.getRemoteSocketAddress().toString();}@Overridepublic void run() {try {InputStream ips=socket.getInputStream();InputStreamReader isr=new InputStreamReader(ips);BufferedReader br=new BufferedReader(isr);while(true) {String str=br.readLine();//将读到的消息发送给所有的客户端for(Socket sk:Serve.socketList) {if(sk!=socket) {OutputStream ops=sk.getOutputStream();OutputStreamWriter osw=new OutputStreamWriter(ops);BufferedWriter bw=new BufferedWriter(osw);bw.write(str+"\n");bw.flush();}}}} catch (Exception e) {// 如果抛出异常,说明连接已经断开,此处为处理用户离开时通知其他客户端的功能// 从List中删除该客户端,并通知其他客户端Serve.socketList.remove(this.socket);for (Socket sk : Serve.socketList) {try {// 从sk上获得输出流OutputStream ops = sk.getOutputStream();OutputStreamWriter osw = new OutputStreamWriter(ops);BufferedWriter bw = new BufferedWriter(osw);bw.write(address + "离开了房间!!\n");bw.flush();} catch (IOException e1) {e1.printStackTrace();}}}}
}

这样子就基本能实现群聊了嘻
下面是拓展
实现一个客户端连接服务端以后,服务器通知其他所有客户端有人上线
即在服务器写一个发信息的线程类,先给连上来的客服端发欢迎消息,然后给其他所有人发送通知。

package serve;import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;/***服务器发送通知的线程类 * @author VastWu**/
public class TellThread extends Thread{private Socket socket;public TellThread(Socket socket) {this.socket=socket;}@Overridepublic void run() {try {OutputStream ops=socket.getOutputStream();OutputStreamWriter osw=new OutputStreamWriter(ops);BufferedWriter bw=new BufferedWriter(osw);String address=socket.getRemoteSocketAddress().toString();bw.write("欢迎"+address+"来到聊天室\n");bw.write("当前在线人数:"+Serve.socketList.size()+"人\r\n");bw.flush();for(Socket sk:Serve.socketList) {if(sk!=socket) {OutputStream ops2=sk.getOutputStream();OutputStreamWriter osw2=new OutputStreamWriter(ops2);BufferedWriter bw2=new BufferedWriter(osw2);bw2.write(address+"进入了聊天室,当前在线人数:"+Serve.socketList.size()+"人\r\n");bw2.flush();}}} catch (Exception e) {e.printStackTrace();}}
}

功能实现:
在这里插入图片描述
更改ip地址即可实现同局域网的聊天…


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

相关文章

web网络聊天室

花了四天时间做了一个简单的web聊天室 前端页面效果大概是下面这个样子 1.登陆界面 2.注册界面 这里首先会检查用户名是否重复&#xff0c; 如果重复&#xff0c;会提示你用户名已存在 反正显示可用 3.聊天室界面 登陆成功会在左边显示登陆人的名称以及当前在线人数。 然后…

局域网通信 | 基于广播实现简易聊天室

前言 事情是这个样子的&#xff0c;实验室的那个横向项目有一个需求&#xff1a;同一个 WIFI 下的设备之间可以实现实时的语音聊天。 于是这两天抽空闲时间捣鼓了一下局域网通信。现在基本实现语音通信了&#xff0c;是基于 UDP 广播实现的&#xff0c;但是不知道是 UDP 丢包…

局域网聊天工具

按企业部门进行划分用户组&#xff1b; 可实现单人、多人之间的文本对话&#xff1b; 方便高效的自动应答系统&#xff1b; 可在任何形式局域网及企业专线网中使用&#xff1b; 谈话窗口中可插入各种心情图标&#xff1b; 强大完备的企业电脑信息查询功能&#xff1b…

局域网实时聊天

本程序可以使用ip也可以使用主机名&#xff0c;这样就可以在打包之后&#xff0c;就不需要一直动态修改IP了 服务器端代码&#xff1a; public partial class FServer : Form{public FServer(){InitializeComponent();TextBox.CheckForIllegalCrossThreadCalls false;}Thread …

简单局域网聊天室--Java版

Java 的Socket编程&#xff1a; 1、TCP协议是面向连接的、可靠的、有序的、以字节流的方式发送数据&#xff0c;通过三次握手方式建立连接&#xff0c;形成传输数据的通道&#xff0c;在连接中进行大量数据的传输&#xff0c;效率会稍低 2、Java中基于TCP协议实现网络通信的类…

局域网聊天

实现局域网聊天&#xff0c;涉及到服务器端和用户端&#xff0c;使用MFC编程实现。 设计服务器端和用户端界面分别建立两个项目&#xff0c;ChatRoomSever和ChatRoomClientChatRoomSever用于创建Socket并监听和接受信息ChatRoomClient用于创建Socket并连接ChatRoomSever 具体…

超赞的8款开源聊天软件

qq曾经风靡一时&#xff0c;作为一名菜鸟&#xff0c;多想自己整一套聊天系统&#xff0c;在局域网内让大家使用。忙里偷闲&#xff0c;搜罗了一堆聊天系统&#xff0c;和我有一样兴趣的同学&#xff0c;可以运行下面的一两款聊天软件&#xff0c;也算是圆了曾经的梦吧&#xf…

局域网间的点对点聊天

聊天已经成为我们日常生活的一部分&#xff0c;各种聊天的软件已经飞满了我们的世界。今天就让我们来探讨一下局域网间的点对点的聊天吧。 我们在Eclipse中创建我们的工程。 其中带有Frame名字字样的工程是有界面的。如何在Eclipse中创建有界面的工程呢&#xff1f;我使用的VE…