多个客户端--多人聊天室
2019-07-09 22:38 更新
1.服务端: 接收一个用户的消息,将其转发给其他连接的用户。
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
/**
* 创建服务器
* 发送数据:输出流
* 接收数据:输入流
*/
public class MyServer {
private List<MyChannel> all = new ArrayList<>();
public static void main(String[] args) throws IOException {
new MyServer().start();
}
public void start() throws IOException {
ServerSocket server = new ServerSocket(8888);
while(true) {
//main线程:用于不断连接用户,将连接放到list中保存,启动专门用于转发消息的线程。
Socket socket = server.accept();
MyChannel myChannel = new MyChannel(socket);
all.add(myChannel);
new Thread(myChannel).start();
}
}
/**
* 一个客户端一条道路,
* 一个客户端一个线程。
* 1.输入流
* 2.输出流
* 3.接收数据
* 4.发送数据
* 成员内部类,静态方法不能访问。
* 服务端转发数据线程。
*/
class MyChannel implements Runnable{
//输入流
private DataInputStream dis;
//输出流
private DataOutputStream dos;
//控制线程的标识符
private boolean isRunning = true;
//初始化建立管道
public MyChannel(Socket socket) {
try {
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
CloseUtil.closeAll(dis, dos);
all.remove(this);
isRunning = false;
}
}
//读取数据
private String receive() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
e.printStackTrace();
CloseUtil.closeAll(dis, dos);
all.remove(this);
isRunning = false;
}
return msg;
}
//发送给this数据
private void send(String msg) {
if(msg == null || msg.equals("")) {
return;
}
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
CloseUtil.closeAll(dis, dos);
all.remove(this);
isRunning = false;
}
}
//发送给其他客户端
private void sendOthers() {
String msg = receive();
//遍历容器
for(MyChannel other : all) {
if(other == this) {
continue;
}
//发送给其他客户端
other.send(msg);
}
}
@Override
public void run() {
while(isRunning){
sendOthers();
}
}
}
}
2.客户端:
import java.io.IOException;
import java.net.Socket;
/**
* 创建客户端:发送数据+接收数据
* 发送数据:输出流
* 接收数据:输入流
* 输出流和输入流应该彼此独立,使用线程处理。
*/
public class MyClient {
public static void main(String[] args) throws IOException {
Socket client = new Socket("localhost", 8888);
//发送 控制台输入并发送到服务端
new Thread(new Send(client)).start();//一条路径
//接收 接收服务端数据并打印
new Thread(new Receive(client)).start();//一条路径
}
}
客户端发送数据--线程 从控制台接收数据,发送到服务端。
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* 发送数据 线程
*/
public class Send implements Runnable{
//控制台输入流
private BufferedReader console;
//管道输出流
private DataOutputStream dos;
//控制线程的标识符
private boolean isRunning = true;
//初始化建立管道
public Send(Socket socket) {
try {
console = new BufferedReader(new InputStreamReader(System.in));
dos = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
isRunning = false;
CloseUtil.closeAll(dos, console);
}
}
/**
* 1.从控制台接收数据
* 2.向服务端发送数据
*/
//1.从控制台接收数据
private String getMsgFromConsole() {
String msg = "";
try {
msg = console.readLine();
} catch (IOException e) {
e.printStackTrace();
isRunning = false;
CloseUtil.closeAll(dos, console);
}
return msg;
}
//2.向服务端发送数据
private void send() {
String msg = getMsgFromConsole();
try {
if(msg != null && !msg.equals("")) {
dos.writeUTF(msg);
dos.flush();//强制刷新
}
} catch (IOException e) {
e.printStackTrace();
isRunning = false;
CloseUtil.closeAll(dos, console);
}
}
@Override
public void run() {
//线程体
while(isRunning) {
send();
}
}
}
客户端接收数据--线程 从服务端接收数据并打印
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
public class Receive implements Runnable{
//输入流
private DataInputStream dis;
//线程标识符
private boolean isRunning = true;
//初始化建立管道
public Receive(Socket socket) {
try {
dis = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
isRunning = false;
CloseUtil.closeAll(dis);
}
}
/**
* 接收数据
*/
private String receive() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
e.printStackTrace();
isRunning = false;
CloseUtil.closeAll(dis);
}
return msg;
}
@Override
public void run() {
//线程体
while(isRunning) {
System.out.println(receive());
}
}
}
3.关闭流工具类:
import java.io.Closeable;
import java.io.IOException;
/**
* 关闭io流的工具
*/
public class CloseUtil {
public static void closeAll(Closeable... io) {
for(Closeable temp : io) {
try {
if(temp != null) {
temp.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
以上内容是否对您有帮助:
← TCP
更多建议: