Java写的简单聊天室(客户端 + 服务端)
基本结构图![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/9f8317f9aa873f1323cc9dff1fddbcca.png)
Client 客户端代码
package day09.test02;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
/**
* 重构聊天室案例,使服务器可以将客户端发送的消息转发给所有客户端,并在
* 每个客户端控制台上显示,并解决多线程安全问题
* @author Admin
*
*/
public class Client {
private Socket socket;
public Client(){
System.out.println("正在连接服务器。。。");
try {
socket = new Socket("localhost",8088);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("连接服务器成功。。。");
}
public void start(){
PrintWriter pw = null;
try {
//开启服务端助手线程--循环输入
Thread serverHandler = new Thread(new ServerHandler());
serverHandler.start();
//打开输出流
pw=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"utf-8")),true);
//循环输出
Scanner scan = new Scanner(System.in);
String line = "";
while(line!=null&&!line.equals("exit")){
line=scan.nextLine();
pw.println(line);
}
scan.close();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 客户端程序入口
* @param args
*/
public static void main (String[]args){
Client client = new Client();
client.start();
}
/**
* 服务端助手:用于循环输入
* @author Loaray
* 2019年1月11日
*/
private class ServerHandler implements Runnable {
public void run(){
BufferedReader br = null;
try {
//打开输入流
br=new BufferedReader(new InputStreamReader(socket.getInputStream(),"utf-8"));
//循环输入
String message = "";
while((message=br.readLine())!=null&&!message.equals("exit")){
// message=br.readLine();
System.out.println(message);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服务端代码
package day09.test02;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* 重构聊天室案例,使服务器可以将客户端发送的消息转发给所有客户端,并在
* 每个客户端控制台上显示,并解决多线程安全问题
* @author Admin
*
*/
public class Server {
private ServerSocket server;
private Collection<PrintWriter> allout = new ArrayList<PrintWriter>();
public Server(){
try {
System.out.println("开始建立服务端。。。");
server = new ServerSocket(8088);
System.out.println("服务端建立完成。。。");
} catch (IOException e) {
e.printStackTrace();
}
}
public void start(){
//等待客户端连接-->连接成功
Socket socket = null;
while(true){
try {
socket = server.accept();
} catch (IOException e) {
e.printStackTrace();
}
//开启客户端助手
Thread clientHandler = new Thread(new ClientHandler(socket));
clientHandler.start();
}
//循环前两步
}
public static void main(String[]args){
Server server = new Server();
server.start();
}
private class ClientHandler implements Runnable{
String host;
Socket socket;
public ClientHandler(Socket socket){
InetAddress address = socket.getInetAddress();
host = address.getHostAddress();
this.socket = socket;
}
public void run(){
//打开输出流
PrintWriter pw = null;
try {
pw=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"utf-8")),true);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//输出流的引用的值复制到allout中-->打印出上线客户端信息和在线人数变化
synchronized(allout){
allout.add(pw);
for(PrintWriter p:allout){
p.println(host+"上线了!\n上线人数是:"+allout.size()+"\n");
}
System.out.println(host+"上线了!\n上线人数是:"+allout.size()+"\n");
}
//打开输入流
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"utf-8"));
//循环 输入-->遍历allout输出输入的内容并说明输入者身份
String message = null;
while((message=br.readLine())!=null&&!message.equals("exit")){
synchronized(allout){
String line = host+"说:"+message;
System.out.println(line);
Iterator<PrintWriter> it = allout.iterator();
while(it.hasNext()){
it.next().println(line);
}
}
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//当不满足循环条件时,跳出循环并关闭套接字
finally{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
synchronized(allout){
allout.remove(pw);
for(PrintWriter p:allout){
p.println(host+"下线了!\n上线人数是:"+allout.size()+"\n");
}
System.out.println(host+"下线了!\n上线人数是:"+allout.size()+"\n");
}
}
}
}
}