客户端输入(name:自己的名字)后,正式加入聊天
服务器代码
package test2019.mon02.聊天系统;
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.HashMap;
import java.util.List;
import java.util.Map;
/**
* 群聊服务器的实现
*/
public class Server {
// 服务器 管理集合 的连接通道
private List list = new ArrayList<>();
private String serverName = "系统消息";
Map tMap = new HashMap<>();
public static void main(String[] args) {
try {
new Server().start();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 启动服务器
*/
private void start() throws IOException {
String port = Tools.getValue("port");
ServerSocket socket = new ServerSocket(port == null ? 9999 : Integer.valueOf(port));
while (true) {
Socket client = socket.accept();
// 来个一个客户端 建立了 通道
Channel channel = new Channel(client);
// 添加到集合中进行管理
list.add(channel);
// 启动线程
Thread thread = new Thread(channel);
thread.start();
tMap.put(channel, thread);
}
}
/**
* 连接通道的类
*/
class Channel implements Runnable {
private boolean startKey = true;
String name = null;
String adress = "";
// 2 个流
private DataInputStream dis = null;
private DataOutputStream dos = null;
// 传入一个socket 进来
public Channel(Socket socket) {
adress = socket.getInetAddress().getHostAddress();
try {
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 接收数据
*
* @return
*/
public String revice() {
String msg = null;
try {
msg = dis.readUTF();
} catch (IOException e) {
if (e.getMessage().equals("Connection reset")) {
this.startKey = false;
list.remove(this);
if (tMap.containsKey(this)) {
Thread t = tMap.get(this);
tMap.remove(this);
System.out.println(this.adress + (this.name == null ? "" : "、" + this.name) + "离开群聊");
if (this.name != null) {
sendMsg(serverName + ":" + this.name + "离开群聊");
}
t.stop();
}
}
}
return msg;
}
/**
* 发送数据
*
* @param msg
*/
public void send(String msg) {
if (msg == null || msg == "") {
return;
}
try {
dos.writeUTF(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 给其他用户发送数据
*/
public void sendOther() {
// 接收数据
String msg = revice();
if (msg == null) {
return;
}
String thisName = this.name;
if (thisName == null) {
System.out.println(this.adress + ":" + msg);
thisName = "匿名";
} else {
System.out.println(this.adress + "、" + this.name + ":" + msg);
}
if (msg.startsWith("name:")) {
String newName = msg.substring(5);
if (newName.equals(this.name)) {
this.send(serverName + ":改名字逗我玩呢?");
return;
}
if (containsName(newName)) {
this.send(serverName + ":你和别人重名了!");
return;
}
if ("匿名".equals(newName) || serverName.equals(newName)) {
this.send(serverName + ":这个名字不能用!");
return;
}
if (this.name == null) {
this.send(serverName + ":" + "您已加入群聊,该群内有成员:" + getNames());
sendMsg(serverName + ":" + newName + "加入群聊");
} else {
sendMsg(serverName + ":" + this.name + "更名为" + newName);
}
this.name = newName;
return;
}
// 给其他用户发送书 循环发送
for (Channel channel : list) {
if (channel == this) { // 不给自己发送数据
continue;
}
if (channel.name == null) {
continue;
}
channel.send(thisName + ":" + msg);
}
}
private String getNames() {
String names = "";
for (Channel channel : list) {
if (channel == this) { // 不给自己发送数据
continue;
}
if (channel.name == null) {
continue;
}
names += channel.name + "、";
}
return names;
}
private void sendMsg(String msg) {
// 给其他用户发送书 循环发送
for (Channel channel : list) {
if (channel == this) { // 不给自己发送数据
continue;
}
if (channel.name == null) {
continue;
}
channel.send(msg);
}
}
private boolean containsName(String newName) {
for (Channel channel : list) {
if (newName.equals(channel.name)) {
return true;
}
}
return false;
}
@Override
public void run() {
while (this.startKey) {
sendOther();
}
}
}
}
客户端代码
package test2019.mon02.聊天系统;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
/**
* @des 客户端 一个读的子线程 一个写的子线程
*/
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
String host = Tools.getValue("host");
System.out.println("host:"+host);
String port = Tools.getValue("port");
// 创建 Socket
Socket socket = new Socket(host, port==null?9999:Integer.valueOf(port));
// 启动线程
// 发送的子线程
new Thread(new Send(socket)).start();
// 接收的子线程
new Thread(new Revice(socket)).start();
}
}
class Revice implements Runnable {
// 数据流 接收数据
private DataInputStream dis = null;
private boolean isRunning = true;
public Revice(Socket socket) {
try {
// 通过 socket 初始化流的操作
dis = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
// 关闭流
IOUitls.closeAll(dis, socket);
isRunning = false;
}
}
/**
* 接收数据
*
* @return
*/
public String revice() {
String msg = null;
try {
// 读取 字符串
msg = dis.readUTF();
} catch (IOException e) {
e.printStackTrace();
// 关闭流
IOUitls.closeAll(dis);
isRunning = false;
}
return msg;
}
@Override
public void run() {
// 循环的接收数据
while (isRunning) {
System.out.println(revice());
}
}
}
class Send implements Runnable {
private Scanner sc = null;
private DataOutputStream dos = null;
private boolean isRunning = true;
public Send(Socket socket) {
try {
this.dos = new DataOutputStream(socket.getOutputStream());
sc = new Scanner(System.in);
} catch (IOException e) {
e.printStackTrace();
IOUitls.closeAll(dos, socket);
isRunning = false;
}
}
/**
* 发送数据
*/
public void send() {
// 获取键盘的输入
System.out.println("请输入:");
String msg = sc.next();
// 发送到服务器端
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
IOUitls.closeAll(dos);
}
}
@Override
public void run() {
while (isRunning) {
send();
}
}
}
class IOUitls {
/**
* 泛型方法 流的关闭
*
* @param arr
*/
public static void closeAll(T... arr) {
for (T t : arr) {
if (t != null) {
try {
t.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
Tools工具类
package test2019.mon02.聊天系统;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* Filename: Test.java Description: Company: sendinfo.com.cn Inc.
*
* @author: guzhangyan
* @date: 2019年2月15日 下午3:18:48
*/
public class Tools {
private static Properties p = new Properties();
static {
try {
File file = new File("data.properties");
//System.out.println(file.getAbsolutePath());
InputStream in = new BufferedInputStream(new FileInputStream(file));
p.load(in);
// p.load(Tools.class.getClassLoader().getResourceAsStream("data.properties"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String getValue(String key) {
return p.getProperty(key);
}
}