2018.9.12最终完成
代码杂乱且冗余,可能存在问题。
//服务器端
package test05;
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.LinkedList;
import java.util.List;
public class Server {
List<Myclient> client = new LinkedList<Myclient>();// new一个线程容器
public void connection() throws IOException {
ServerSocket ss = new ServerSocket(11165);// 服务器套接字
while (true) {
Socket s = ss.accept();
Myclient my = new Myclient(s);// 实例化封装了服务器IO功能的内部类
client.add(my);
System.out.println("聊天室有" + client.size() + "人");
new Thread(my).start();// 启动内部类的多线程功能
}
}
private class Myclient implements Runnable {
BufferedReader br;
BufferedWriter bw;
boolean flag = true;// 多线程标识
String name;
static final String str = "欢迎进入聊天室当前聊天室有:";
public Myclient(Socket s) {
try {
// IO管道
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
bw = new BufferedWriter(new OutputStreamWriter((s.getOutputStream())));
} catch (IOException e) {
Close.closeAll(br, bw);
}
}
public void off() {
flag = false; // 如果不用该方式控制多线程那么关闭到
client.remove(this); // 剩下一个用户服务器就会异常导致服务器
Close.closeAll(bw); // 关闭。因为链表就剩一个对象无法进行
// 对其他对象进行遍历。
}
@Override
public void run() {
try {
this.name = br.readLine();
} catch (IOException e) {
off();
}
// 欢迎语
String welcoming = "系统消息:" + name + str + client.size() + "人";
this.send(welcoming);
while (flag) {
sendOther();
}
client.remove(this);
}
// 接受需要转发的信息
public String receive() {
String msg = null;
try {
msg = br.readLine();
} catch (IOException e) {
int number = client.size() - 1;
sendOther1(" 系统消息:" + this.name + "用户已经退出聊天室" + "当前人数为" + number);
off();
}
return msg;
}
public void send(String data) {
try {
if (null != data && !data.equals("")) {
bw.write(data);
bw.newLine();
bw.flush();
}
} catch (IOException e) {
off();
}
}
public void sendOther1(String data1) {
for (Myclient other : client) {
if (this != other) {
other.send(data1);
} else {
continue;
}
}
}
// 发送内容给其他人
public void sendOther() {
String data = null;
data = this.receive();
if (data.startsWith("@") && data.indexOf(":") > -1) {// 该地方使用的是英文“:”如果使用中文“:”就无法私聊
String msg = data.substring(1, data.indexOf(":"));
String msg1 = data.substring(data.indexOf(":") + 1);
for (Myclient other : client) {
if (other.name.equals(msg)) {
String Privatechat = this.name + "对你小声说 " + msg1;
other.send(Privatechat);
}
}
} else {
for (Myclient other : client) {
if (this != other) {
String mag = this.name + ":" + data;
other.send(mag);
} else {
continue;
}
}
}
}
}
public static void main(String[] args) throws IOException {
new Server().connection();
}
}
//客户端
package test05;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public Socket connetion() throws UnknownHostException, IOException {
Socket s=new Socket("127.0.0.1",11165);//套接字
return s;
}
public static void main(String[] args) throws IOException {
Socket s=new Client().connetion();//获得套接字
new Thread(new ClientSend(s)).start(); //发送管道线程
new Thread(new ClientReceive(s)).start();//接收管道线程
}
}
//客户端接收类
package test05;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class ClientReceive implements Runnable {
BufferedReader br;
String msg = "";
// 管道
public ClientReceive(Socket s) {
try {
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
} catch (IOException e) {
Close.closeAll(br);
}
}
// 接受内容
public void receive() throws IOException {
msg = br.readLine();
}
@Override
public void run() {
while (true) {
try {
receive();
System.out.println(msg);
msg = "";
} catch (IOException e) {
Close.closeAll(br);
}
}
}
}
//客户端发送类
package test05;
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 ClientSend extends Client implements Runnable {
BufferedReader console;
BufferedWriter bw;
private String name;
private boolean mark = true;
static final String str2 = "请输入您的名字";
public ClientSend(Socket s) throws IOException {
bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));// 管道
usreName();
send(name);
}
// 获得控制台所需发送内容
public String consoleEnter() throws IOException {
String msg = null;
console = new BufferedReader(new InputStreamReader(System.in));
msg = console.readLine();
return msg;
}
// 发送内容
public void send(String msg) throws IOException {
if (null != msg && !msg.equals("")) {// 判断发送内容是否为空
bw.write(msg);
bw.newLine();
bw.flush();
}
}
// 用户输入用户名
private void usreName() throws IOException {
while (mark) {
System.out.println(str2);
name = consoleEnter();
if (name.length() < 11 && name != null) {
mark = false;
}
}
}
@Override
public void run() {
while (true) {
try {
String msg = consoleEnter();
send(msg);
} catch (IOException e) {
Close.closeAll(bw, console);
}
}
}
}
//关闭工具类
package test05;
import java.io.Closeable;
/**
* 关闭流的方法
* @author Administrator
*
*/
public class Close {
public static void closeAll(Closeable... io){
for(Closeable temp:io){
try {
if (null != temp) {
temp.close();
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
}