功能描述即分解步骤:
1.服务器端接收客户端消息
2.服务器接收并返回客户端消息
3.客户端可以通过键盘持续的发送消息并接收服务端返回的消息
4.服务器同时处理多个客户端请求
5。让聊天室内的人可以看到彼此的消息
服务器端代码
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Server {
private static final List<BufferedWriter> list = new ArrayList();
private static final Object lock = new Object();//创建一把锁
public static void start() throws Exception {
ServerSocket ssocket = new ServerSocket(9000);//监听一个端口
System.out.println("服务器开启。。。。。。。");
while (true) {
Socket client = ssocket.accept();//此时会发生阻塞,等待客户端连接进来
System.out.println(">>>有新客户端连接进来");
new Thread(new Runnable() {
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
synchronized (lock) {
//将新用户加入到集合里
list.add(bw);
}
String data = null;
while (null != (data = br.readLine())) {
Iterator<BufferedWriter> iterator = list.iterator();
while (iterator.hasNext()) {
BufferedWriter bufw = iterator.next();
try {
bufw.write(data);
bufw.newLine();
bufw.flush();
}catch (Exception e) {
synchronized (lock) {
iterator.remove();
}
}
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
}).start();;
}
}
public static void main(String[] args) throws Exception {
Server.start();
}
}
客户端代码
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class Client {
public static void start() throws Exception {
String ip = "localhost";
int port = 9000;
Socket socket = new Socket(ip,port);
//负责读取键盘输入的消息并发送给服务器端
new Thread(new Runnable() {
@Override
public void run() {
try {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader keyIn = new BufferedReader(new InputStreamReader(System.in));//通过键盘进行输入
String msg = null;
while (null != (msg = keyIn.readLine())) {
bw.write(msg);
bw.newLine();//添加换行
bw.flush();
}
}catch (Exception e) {
e.printStackTrace();
}
}
},"clientWriter").start();
//负责读取服务端发送的消息
new Thread(new Runnable() {
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String data = null;
while (null != (data = br.readLine())) {
System.out.println(">>>>" + data);
}
} catch(Exception e) {
e.printStackTrace();
}
}
},"clientReader").start();
}
public static void main(String[] args) throws Exception {
Client.start();
}
}
总结:
该聊天室的功能虽然简单,但是运用到的知识非常广泛。涉及到面向对象,集合,IO,多线程,网络编程等知识,几乎涵盖了javase的重要基础部分。非常值得学习。但是以上代码还是有优化的空间。根据JDK8新特性Lamda表达式,我们可以简化启动线程部分的代码块。优化部分的代码块如下所示
new Thread(() -> {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
synchronized (lock) {
//将新用户加入到集合里
list.add(bw);
}
String data = null;
while (null != (data = br.readLine())) {
Iterator<BufferedWriter> iterator = list.iterator();//通过迭代器来遍历集合
while (iterator.hasNext()) {
BufferedWriter bufw = iterator.next();
try {
bufw.write(data);
bufw.newLine();
bufw.flush();
}catch (Exception e) {
synchronized (lock) {
iterator.remove();
}
}
}
}
} catch(Exception e) {
e.printStackTrace();
}
}).start();
//负责读取键盘输入的消息并发送给服务器端
new Thread(() -> {
try {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader keyIn = new BufferedReader(new InputStreamReader(System.in));//通过键盘进行输入
String msg = null;
while (null != (msg = keyIn.readLine())) {
bw.write(msg);
bw.newLine();//添加换行
bw.flush();
}
}catch (Exception e) {
e.printStackTrace();
}
},"clientWriter").start();
//负责读取服务端发送的消息
new Thread(() -> {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String data = null;
while (null != (data = br.readLine())) {
System.out.println(">>>>" + data);
}
} catch(Exception e) {
e.printStackTrace();
}
},"clientReader").start();