一个基于Socket的简单局域网通讯聊天室
1.服务器
package com.socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
/**
* @Authro: QYF
* @Time:2020/10/27 23:33
*/
public class ChatServer {
//存储在线信息
private static ArrayList<TongXinThread> list= new ArrayList<TongXinThread>();
static class ServerThread extends Thread{
@Override
public void run() {
try {
ServerSocket ss = new ServerSocket(8000);
System.out.println("服务器已启动");
while (true) {
//等待连接
Socket s = ss.accept();
TongXinThread t = new TongXinThread(s);
t.start();
System.out.println("一个客户端已上线");
}
} catch (Exception e) {
System.out.println("8000端口被占用,或服务异常停止");
}
}
}
static class TongXinThread extends Thread{
Socket s;
BufferedReader in;
PrintWriter out;
private String name;
//构造方法
public TongXinThread(Socket s) {
this.s = s;
}
public void send(String msg) {
out.println(msg);
out.flush();
}
public void sendAll(String msg) {
synchronized (list) {
for (TongXinThread t : list) {
t.send(msg);
}
}
}
@Override
public void run() {
try {
in = new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8"));
out = new PrintWriter(new OutputStreamWriter(s.getOutputStream(), "UTF-8"));
//1.收昵称, 2.发欢迎 3.通信对象加入集合 4.群发上线消息
this.name = in.readLine();
send("欢迎进入激情聊天室");
//加入在线集合
synchronized (list) {
list.add(this);
}
//设置超时时间60秒
s.setSoTimeout(60000);
sendAll(name+"进入了聊天室,在线人数: "+list.size());
//持续接收这个客户端的聊天内容,并群发
String line;
//超过三次提示强制下线
int count = 0;
while (true) {
try {
line = in.readLine();
//重置超时次数
count = 0;
} catch (SocketTimeoutException e) {
count++;
if (count==4) {
send("*** 您已经被踢出聊天室 ***");
s.close();
break;
}
send("*** 请积极参与聊天("+count+"/3) ***");
continue;
}
if (line == null) {
break;
}
sendAll(name+": "+line);
}
} catch (Exception e) {
}
//断开,删除用户信息
synchronized (list) {
list.remove(this);
}
sendAll(name+"离开了聊天室,当前在线人数: "+list.size());
}
}
public static void main(String[] args) {
new ServerThread().start();
}
}
2.客户端
package com.socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
/**
* @Authro: QYF
* @Time:2020/10/27 23:44
*/
public class ChatClient {
private Socket s;
private BufferedReader in;
private PrintWriter out;
private String name;
//当用户在输入时,停止接收消息,用队列暂存
private Queue<String> queue = new LinkedList<String>();
//用户是否在输入内容
private boolean inputFlag;
public void launch() {
try {
//连接的服务器地址和端口
this.s = new Socket("127.0.0.1", 8000);
//接收数据
in = new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8"));
//传输数据
out = new PrintWriter(new OutputStreamWriter(s.getOutputStream(), "UTF-8"));
//发昵称
System.out.print("请先起个名字:");
this.name = new Scanner(System.in).nextLine();
out.println(name);//必须有 ln
out.flush();
//接收线程
new Thread(()->{
receive();
}).start();
//打印线程
Thread t2 = new Thread(()->{
print();
});
t2.setDaemon(true);
t2.start();
//输入线程
Thread t3 = new Thread(()->{
input();
});
t3.setDaemon(true);
t3.start();
} catch (Exception e) {
System.out.println("不能连接服务器");
e.printStackTrace();
}
}
protected void print() {
while (true) {
synchronized (queue) {
while (queue.isEmpty() || inputFlag) {
try {
queue.wait();
} catch (InterruptedException e) {
}
}
String msg = queue.poll();
System.out.println(msg);
}
}
}
protected void input() {
System.out.println("按回车输入聊天内容");
while (true) {
new Scanner(System.in).nextLine();
//打开输入开关
inputFlag = true;
System.out.print("输入聊天内容:");
String s = new Scanner(System.in).nextLine();
out.println(s);//必须有ln
out.flush();
//关闭输入开关
inputFlag = false;
synchronized (queue) {
//通知打印线程可以继续打印
queue.notifyAll();
}
}
}
protected void receive() {
try {
String line;
while((line = in.readLine()) != null) {
synchronized (queue) {
queue.offer(line);
queue.notifyAll();
}
}
} catch (Exception e) {
}
System.out.println("已经与服务器断开连接");
}
public static void main(String[] args) {
new ChatClient().launch();
}
}
客户端一样的代码.可以多复制几份.我这里是开了三个.
3.启动服务器ChatServer
输出结果:
服务器已启动
一个客户端已上线
一个客户端已上线
一个客户端已上线
4.启动连续激动三个客户端ChatClient
输出结果;
请先起个名字:西门庆
欢迎进入激情聊天室
西门庆进入了聊天室,在线人数: 1
按回车输入聊天内容
潘金莲进入了聊天室,在线人数: 2
武大郎进入了聊天室,在线人数: 3
输入聊天内容:有人在么
西门庆: 有人在么
潘金莲: 你好
武大郎: 我是谁?我在哪?
请先起个名字:潘金莲
欢迎进入激情聊天室
潘金莲进入了聊天室,在线人数: 2
按回车输入聊天内容
武大郎进入了聊天室,在线人数: 3
西门庆: 有人在么
输入聊天内容:你好
潘金莲: 你好
武大郎: 我是谁?我在哪?
西门庆离开了聊天室,当前在线人数: 2
请先起个名字:武大郎
欢迎进入激情聊天室
武大郎进入了聊天室,在线人数: 3
按回车输入聊天内容
西门庆: 有人在么
潘金莲: 你好
输入聊天内容:我是谁?我在哪?
武大郎: 我是谁?我在哪?
西门庆离开了聊天室,当前在线人数: 2
潘金莲离开了聊天室,当前在线人数: 1