网络聊天室
这是一个基于TCP/IP协议的多人网络聊天室,客户端发送消息给服务端,服务端再将消息发送给所有的客户端,实现多人群聊。需要源码的请参见这里,提取码:9527。
服务端
Server
创建服务,启动聊天线程。
public class Server {
/**
* 对外提供的端口号
*/
private int port;
/**
* 用于记录所有产生的socket对象
*/
public volatile static List<Socket> client = new ArrayList<>();
public Server(int port) {
this.port = port;
}
public void startServer() {
try {
//创建服务
ServerSocket server = new ServerSocket(port);
Tools.tips("服务已开启,等待连接。。。");
while (true) {
//监听客户端连接
Socket s = server.accept();
//将获取的Socket对象添加到集合中
client.add(s);
Tools.tips("客户端已连接:" + Tools.ip(s));
//启动聊天服务线程
new TalkingServer(s).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Server(5678).startServer();
}
}
MsgServer
消息接收转发服务线程,用于接收客户端发送的消息,再将其转发给所有的客户端。
/**
* 消息接收转发线程
*/
public class MsgServer extends Thread {
private Socket s;
public MsgServer(Socket s) {
this.s = s;
}
@Override
public void run() {
try {
//读取接收到的来自Socket的消息
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
//临时变量,用于接收每次读取的文本消息
String msg = null;
while ((msg = br.readLine()) != null) {
for (Socket s : Server.client) {
String content = Tools.date(System.currentTimeMillis()) + " " + Tools.host(s) + ":" + msg;
Tools.sendMsg(s.getOutputStream(), content);
}
}
} catch (IOException e) {
Tools.tips("客户断开连接:" + Tools.ip(s));
//从集合中移除该对象
Server.client.remove(s);
}
}
}
客户端
Client
客户端:与服务端建立连接,进行消息发送,并同步启动消息接收线程,实现发消息的同时接收消息。
public class Client {
/**
* 远程服务的ip地址
*/
private String ip;
/**
* 远程服务应用的端口
*/
private int port;
public Client(String ip, int port) {
this.ip = ip;
this.port = port;
}
public void startChat() {
try {
Socket s = new Socket(ip, port);
MsgReceiver mr = new MsgReceiver(s);
mr.setDaemon(true);
mr.start();
//获取文本扫描对象
Scanner sc = new Scanner(System.in);
OutputStream os = s.getOutputStream();
String msg = "";
while (!"quit".equals(msg)) {
msg = sc.nextLine();
Tools.sendMsg(os, msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Client("192.168.7.170", 5678).startChat();
}
}
MsgReceiver
消息接收线程,用于接收消息,并将聊天记录按日期存入文件中进行保存。
/**
* 消息接收线程
*/
public class MsgReceiver extends Thread {
private Socket s;
private File dir;
{
FileSystemView fsv = FileSystemView.getFileSystemView();
dir = fsv.getHomeDirectory();
}
public MsgReceiver(Socket s) {
this.s = s;
}
@Override
public void run() {
BufferedReader br = null;
try {
//获取Socket中的输入流
InputStream is = s.getInputStream();
//将字节输入流转换为字符输出流
InputStreamReader isr = new InputStreamReader(is);
//将低级流包装为缓冲流
br = new BufferedReader(isr);
String msg = null;
//循环读取
while ((msg = br.readLine()) != null) {
Tools.tips(msg);
chatRecord(msg, dir);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 保存聊天记录
*/
public void chatRecord(String msg, File dir) throws IOException {
//获取当前时间
LocalDate date = LocalDate.now();
//获取目录下文件集合
File[] files = dir.listFiles();
//定义变量用于标记当前日期的文件是否存在,默认不存在
boolean b = false;
if (files != null) {
for (File f : files) {
//判断文件存在
if (f.getName().equals(date.toString() + ".txt")) {
//将聊天记录写入文件中
writeRecord(f, msg);
//标记文件存在
b = true;
}
}
}
//如果文件不存在
if (!b) {
String fileName = date.toString() + ".txt";
//创建当天日期的文件
File file = new File(dir, fileName);
//将聊天记录写入文件中
writeRecord(file, msg);
}
}
/**
* 将聊天记录写入文件中
*
* @param f
* @param msg
* @throws IOException
*/
public void writeRecord(File f, String msg) throws IOException {
//获取文件字节输出流
OutputStream os = new FileOutputStream(f, true);
//将字节输出流包装为字符打印流
PrintWriter pw = new PrintWriter(new OutputStreamWriter(os));
//将消息写入
pw.println(msg);
//刷新,将缓冲区的字符写入文件中
pw.flush();
}
}