import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.util.Scanner;
import java.util.StringTokenizer;
public class ChatClient {
// 创建一个Socket
private static Socket client = null;
// 定义输入流变量
private static DataInputStream di = null;
// 定义输出流变量
private static DataOutputStream dos = null;
// 创建scanner对象接收数据
Scanner sc = new Scanner(System.in);
// 定义一个String变量保存用户名
static String name;
// 定义一个布尔值来判断是否循环接受用户名
boolean falg = true;
public static void main(String args[]) {
// 创建对象
ChatClient cc = new ChatClient();
// 创建客户端的socket对象
client = new Socket();
// 调用方法
cc.connect();
// 调用方法
cc.send();
}
// 连接
public void connect() {
// 创建客户端的socket对象
client = new Socket();
// 定义一个String接收IP地址
String IP = null;
// 定义一个int端口号
int port = 0;
System.out.println("***!!Welcome!!***");
try {
System.out.println("输入服务器的默认地址是0或127.0.0.1");
// 接收一个IP保存到string对象中
IP = sc.nextLine();
// 匹配接收到的IP,接收到后将IP赋值为默认
if (IP.equalsIgnoreCase("0")) {
IP = "";
}
//设置端口号
port = 8000;
} catch (Exception e) {
}
try {
// 从给定的主机名得到ip存入inetaddress对象中
InetAddress address = InetAddress.getByName(IP);
// 根据得到的ip和端口号创建套接字地址
InetSocketAddress socketaddress = new InetSocketAddress(address,
port);
// 将客户端的套接字链接到服务器
try {
// 连接服务器与客户端
client.connect(socketaddress);
// 判断是否有连接
if (client.isConnected()) {
// 调用方法
runn();
} else {
client.connect(socketaddress);
// 调用方法
connect();
}
} catch (SocketException e) {
System.out.println("不能连接到服务器,请重新输入");
// 调用connect()重新连接
connect();
}
} catch (Exception e) {
System.out.println("不能连接到服务器,请重新输入");
// 调用connect()重新连接
connect();
}
}
public void runn() {
try {
// 定义read对象
ClientThread read = null;
// 创建read对象
read = new ClientThread();
// 创建readdata线程对象
Thread readData = new Thread(read);
// 封装一个DataInputStream对象得到输入流
di = new DataInputStream(client.getInputStream());
// 封装一个DataOutputStream对象得到输出流
dos = new DataOutputStream(client.getOutputStream());
// 接受用户名
while (falg) {
System.out.println("请输入用户名:");
name = sc.next();
System.out.println(name + "上线了");
System.out.println("欢迎进入聊天室,需要帮助请输入/A");
dos.writeUTF(name);
dos.flush();
read.setDataInputStream(di);
// 启动线程
readData.start();
// 改变flag中断循环
falg = false;
}
} catch (IOException e) {
}
}
// 写入信息
@SuppressWarnings("deprecation")
public void send() {
// 循环接收发送的消息
System.out.println("请输入内容:");
while (sc.hasNext()) {
String mess;
mess = sc.nextLine();
if (mess.equalsIgnoreCase("/0")) {
System.exit(0);
} else if (mess.equalsIgnoreCase("/D")) {
try {
File file = new File("qq.txt");
di = new DataInputStream(new FileInputStream(file));
String info = null;
System.out.println("1 微笑;2 哭泣;3 疑问;4 加油;5 喔耶~;");
System.out.println("6 幸福;7 好冷;8 刺眼;9 昏倒;10 幸福;");
System.out.println("请选择表情:");
String age = sc.next();
while ((info = di.readLine()) != null) {
StringTokenizer stri = new StringTokenizer(info, ".");
String inn = stri.nextToken();
String in = stri.nextToken();
// System.out.println(in);
if (age.equals(inn)) {
dos.writeUTF(in);
break;
}
}
} catch (Exception e) {
}
}
if (mess.equals("/D")) {
} else {
select(mess);
}
}
}
// 将消息发送给服务器
public void select(String mess) {
// 判断输入的信息
if (mess.equalsIgnoreCase("/A")) {
// 匹配上调用helpList()方法
helpList();
} else if (mess.equalsIgnoreCase("/C")) {
try {
System.out.println("请输入你要查看的聊天记录的名字");
String str1 = sc.next();
File file = new File(str1 + ".txt");
BufferedReader bf = new BufferedReader(new FileReader(file));
String str = null;
while ((str = bf.readLine()) != null) {
System.out.println(str);
}
bf.close();
} catch (IOException e) {
}
} else {
try {
// 将消息发送给服务器
dos.writeUTF(mess);
// 清空输出流
dos.flush();
} catch (IOException e) {
}
}
}
public void helpList() {
System.out.println("提示:进入聊天室,默认公聊!!");
System.out.println("/B 用户在线列表,用户/信息 私聊,/C 查看聊天记录,/D 发送表情,/0 退出系统");
}
}
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class ClientThread implements Runnable {
// 定义一个DataInputStream变量
DataInputStream di;
// 定义一个string对象接收服务器发送的消息
String str;
boolean ff=true;
public void setDataInputStream(DataInputStream di) {
this.di = di;
}
public void run() {
while (true) {
try {
// 从流中读取信息
str = di.readUTF();
// 调用writeFile将信息写入文件中
writeFile(str);
// 显示信息
System.out.println(str);
} catch (IOException e) {
// 服务器断开后客户端显示提示信息
System.out.println("服务断开~~~~~~~");
// 终止客户端
System.exit(0);
}
}
}
public void writeFile(String str2) {
try {
// 创建一个文件
File file = new File(ChatClient.name + ".txt");
FileWriter fw = new FileWriter(file, true);
BufferedWriter bw = new BufferedWriter(fw);
bw.write(str2);
// 写入一个行分隔符
bw.newLine();
// 关闭缓冲流
bw.close();
// 关闭字符输出流
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.StringTokenizer;
public class ServerThread implements Runnable {
// 定义一个socket变量
Socket client = null;
// 定义一个Datainputstream变量
DataInputStream di = null;
// 定义一个Dataoutputstream变量
DataOutputStream dos = null;
// 定义一个变量保存连接当前线程的用户名
String name = null;
// 创建一个hashtable对象用来保存所有的为客户端开辟的线程对象
static Hashtable<String, ServerThread> clientlist = new Hashtable<String, ServerThread>();
public ServerThread() {
}
public ServerThread(Socket client, String name) {
try {
// 将传入的client赋值给成员变量的client
this.client = client;
// 将传入的name赋值给成员变量的name
this.name = name;
// 将服务器的输出流封装到DataInputStream中
di = new DataInputStream(client.getInputStream());
// 将服务器的输出流封装到DataOutputStream中
dos = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
}
}
public void run() {
try {
// 添加当前对象到hashtable
clientlist.put(name, this);
// 发送新用户进入的消息给所有客户端
sendallClient(name + "进入聊天室");
while (true) {
// 定义一个string对象接受从流中读取到的信息
String mess = di.readUTF();
// 创建一个stringtokenizer对象分析接收到的消息
StringTokenizer str = new StringTokenizer(mess, "/");
// 判断截取到的信息有没分隔符
// 如果有分隔符则判断为私聊发送信息
if (str.countTokens() == 2) {
// 得到要发送私聊信息用户的姓名
String nameid = str.nextToken();
// 得到要发送的私聊信息
String message = str.nextToken();
// 调用发sendclient送私聊信息
sendClient(nameid, message);
// 没有分隔符或者有多个分隔符是信息默认为公聊发送
} else if (mess.equalsIgnoreCase("/B")) {
// 匹配到调用getlist方法
getList();
// 判断信息是否与-change匹配
} else if (mess.equalsIgnoreCase("/0")) {
System.out.println("name" + "退出聊天室");
break;
} else if (str.countTokens() == 1 || str.countTokens() >= 3) {
// 调用sendallclient发送公聊信息
sendallClient(name + "说:" + mess);
}
}
client.close();
} catch (Exception e) {
} finally {
// 清除客户端信息
clientlist.remove(name);
File file=new File(name+".txt");
//文件删除
file.delete();
// 有人退出时,给所有人发送退出信息
sendallClient(name + "退出聊天室");
System.out.println(getDate() + " " + name + "退出聊天室");
}
}
// 公聊
public void sendallClient(String mess) {
// 获得clientlist中值得ServerThread放入枚举集合中
Enumeration<ServerThread> allclients = clientlist.elements();
// 遍历所有客户
while (allclients.hasMoreElements()) {
// 枚举中还有元素是,返回此举的下一个元素
ServerThread st = (ServerThread) allclients.nextElement();
try {
// 将信息写入流中
st.dos.writeUTF(getDate() + "\t" + mess);
// 刷新流
st.dos.flush();
} catch (IOException e) {
Thread th = new Thread(st);
// 产生异常中断此线程
th.interrupt();
}
}
}
// 私聊
public void sendClient(String name1, String mess) {
ServerThread st = clientlist.get(name1);
ServerThread st1 = clientlist.get(name);
try {
// 将要发送的信息保存到流中
st.dos.writeUTF(getDate() + "\t" + name + "对你说:\t" + mess);
// 刷新流
st.dos.flush();
// 把信息发给原客户端
st1.dos.writeUTF(getDate() + "\t你对" + name1 + "说:\t" + mess);
// 刷新流
st1.dos.flush();
} catch (IOException e) {
System.out.println("你发送的信息有误,请重新发送!");
sendClient(name1, mess);
}
}
public boolean checkp(String str) {
boolean flag = true;
// 得到所有的用户名
Enumeration<String> checkname = clientlist.keys();
// 循环检查用户名
while (checkname.hasMoreElements()) {
// 枚举中还有元素是,返回此举的下一个元素
String sn = (String) checkname.nextElement();
// 判断用户名是否重复,重复的话返回false
if (str.equalsIgnoreCase(sn)) {
// 返回false
flag = false;
// 判断用户名是否为空
} else if (str.equalsIgnoreCase("")) {
// 返回false
flag = false;
}
}
return flag;
}
// 关闭服务器
public void guanBi() {
if (!(client == null)) {
try {
client.close();
System.out.println("客户端退出此系统");
} catch (IOException e) {
}
}
}
// 显示用户在线
public void getList() {
// 获得所有键的枚举
Enumeration<String> checkname = clientlist.keys();
// 通过用户名获得线程对象
ServerThread st = clientlist.get(name);
try {
// 写入信息
st.dos.writeUTF("在线用户列表");
// 写入用户在线人数
st.dos.writeUTF(clientlist.size() + ":人在线");
} catch (IOException e1) {
e1.printStackTrace();
}
// 便利枚举
while (checkname.hasMoreElements()) {
// 枚举中还有元素是,返回此举的下一个元素
String sn = (String) checkname.nextElement();
try {
// 将用户信息写入流中
st.dos.writeUTF("用户名称:" + sn);
// 清空输出流
st.dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 时间
public String getDate() {
// 获得data对象
Date nowTime = new Date();
// 创建格式化参数
String pattern = "HH:mm:ss";
// 创建SimpleDateFormat对象
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
// 定义一个变量接收时间
String timePattern = sdf.format(nowTime);
// 返回当前时间
return timePattern;
}
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class ChatServer {
// 定义一个serversocket对象
private static ServerSocket server = null;
// 定义一个socket对象
private static Socket client = null;
// 定义一个变量用来保存客户端的用户名
private static String name;
// 定义一个布尔值变量
private static boolean falg = true;
// 定义输入流变量
private static DataInputStream di = null;
// 定义输出流变量
private static DataOutputStream dos = null;
public static void main(String args[]) {
// 创建ServerThread对象
ServerThread st = new ServerThread();
while (true) {
try {
// 创建serversocket对象指定端口号为8000
server = new ServerSocket(8000);
} catch (IOException e) {
System.out.println("正在监听!!");
}
try {
System.out.println("等待客户端连接....");
// 将客户端的套接字与服务器的套接字连接起来
client = server.accept();
System.out.println("连接成功!!");
// 将服务器的输入流封装到DataInputStream中
di = new DataInputStream(client.getInputStream());
// 将服务器的输出流封装到DataInputStream中
dos = new DataOutputStream(client.getOutputStream());
// 从流中读取用户名
while (falg) {
name = di.readUTF();
if (st.checkp(name)) {
System.out.println("客户的地址:" + client.getInetAddress()
+ "\t" + name + ":进入聊天室");
// 将falg变为false
falg = false;
} else {
// 清空输出流
dos.flush();
}
}
} catch (IOException e) {
System.out.println("正在等待客户端呼叫......");
}
// 判断是否有客户端连接到服务器
if (client.isConnected()) {
// 创建服务器端的收发信息线程对象
ServerThread sth = new ServerThread(client, name);
Thread th = new Thread(sth);
// 启动线程
th.start();
falg = true;
}
}
}
}