Cilent
package demo.client;
import demo.common.Constant;
import javax.swing.;
import java.awt.;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.Socket;
//多线程、IO、异常、集合、面向对象、网络编程
//gui
public class Client {
// 以下 是登录窗口的 属性
private JFrame loginFrame = null;
private JPanel loginJContentPane = null;
private JLabel loginlabShowMsg = null; //
private JLabel loginJlabName = null;
private JTextField loginTxtName = null;//
private JButton loginBtnLogin = null;//
// 以下 是主窗口的 属性
private JFrame mainFrame = null;
private JPanel mainJContentPane = null;
private TextArea mainShowTalk = null;
private JButton mainBtnSend = null;
private JLabel mainLabToSay = null;
private JTextField mainYouInput = null;
//io流
private BufferedOutputStream bos;
private BufferedInputStream bis;
private String colseId;
// 初始化 主窗口
private void initializeMainFrame() {
mainFrame.setSize(406, 309);
mainFrame.setResizable(false);
if (mainJContentPane == null) {
mainLabToSay = new JLabel();
mainLabToSay.setBounds(new Rectangle(4, 243, 35, 27));
mainLabToSay.setText("说吧:");
mainJContentPane = new JPanel();
mainJContentPane.setLayout(null);
if (mainShowTalk == null) {
mainShowTalk = new TextArea();
mainShowTalk.setBounds(new Rectangle(4, 2, 395, 235));
mainShowTalk
.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
}
mainJContentPane.add(mainShowTalk, null);
if (mainBtnSend == null) {
mainBtnSend = new JButton();
mainBtnSend.setBounds(new Rectangle(328, 243, 66, 24));
mainBtnSend
.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
mainBtnSend.setFont(new Font("Dialog", Font.BOLD | Font.ITALIC,
14));
mainBtnSend.setText("发送");
mainBtnSend.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//主窗口 点击发送按钮消息
send();
}
});
}
mainJContentPane.add(mainBtnSend, null);
mainJContentPane.add(mainLabToSay, null);
if (mainYouInput == null) {
mainYouInput = new JTextField();
mainYouInput.setText(null);
mainYouInput.setBounds(new Rectangle(43, 242, 277, 28));
mainYouInput.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//主窗口 回车 发送按钮消息
send();
}
});
}
mainJContentPane.add(mainYouInput, null);
}
mainFrame.setContentPane(mainJContentPane);
mainFrame.setTitle("聊天窗口");
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
// 关闭聊天室窗口
close();
}
});
}
//发送消息
private void send() {
String input = mainYouInput.getText().trim();
if(input.length()>0){
//发送
try {
bos.write(input.getBytes());
bos.flush();
//清空输入框
mainYouInput.setText("");
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 初始化 登录窗口
private void initializeLoginFrame() {
if (loginJContentPane == null) {
loginlabShowMsg = new JLabel();
loginlabShowMsg.setBounds(new Rectangle(102, 38, 138, 30));
loginlabShowMsg.setFont(new Font("Dialog", Font.BOLD, 12));
loginlabShowMsg.setForeground(Color.red);
//loginlabShowMsg.setText("名字重复,隐姓埋名吧");
loginlabShowMsg.setText(null);
loginJlabName = new JLabel();
loginJlabName.setBounds(new Rectangle(11, 3, 103, 30));
loginJlabName.setFont(new Font("Dialog", Font.BOLD, 18));
loginJlabName.setForeground(Color.blue);
loginJlabName.setText("先报个名吧:");
loginJContentPane = new JPanel();
loginJContentPane.setLayout(null);
loginJContentPane.add(loginJlabName, null);
if (loginTxtName == null) {
loginTxtName = new JTextField();
loginTxtName.setBounds(new Rectangle(139, 2, 87, 33));
loginTxtName.setFont(new Font("Dialog", Font.PLAIN, 18));
loginTxtName.setText(null);
// 向 loginTxtName 添加 动作事件
loginTxtName.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 当 loginTxtName 被敲回车,执行登录操作
login();
}
});
}
if (loginBtnLogin == null) {
loginBtnLogin = new JButton();
loginBtnLogin.setBounds(new Rectangle(21, 37, 73, 31));
loginBtnLogin.setFont(new Font("Dialog", Font.BOLD, 18));
loginBtnLogin.setText("加入");
// 向 loginBtnLogin 添加 动作事件
loginBtnLogin.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 当 loginBtnLogin 被敲点击时,执行登录操作
login();
}
});
}
loginJContentPane.add(loginTxtName, null);
loginJContentPane.add(loginBtnLogin, null);
loginJContentPane.add(loginlabShowMsg, null);
}
loginFrame.setSize(261, 106);
loginFrame.setResizable(false);
loginFrame.setContentPane(loginJContentPane);
loginFrame.setTitle("在线聊天室");
// 添加窗口 关闭事件
loginFrame.addWindowListener(new WindowAdapter() {
// 如果 new 监听器(WindowListener) ,必须实现每一个方法
// 如果 new 适配器(WindowListener) ,需要哪个就实现哪个
public void windowClosing(WindowEvent e) {
// 调用 close 方法关闭客户端
close();
}
});
}
//关闭窗口
private void close() {
try {
bos.write(colseId.getBytes());
bos.flush();
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
}
}
//登录方法
private void login() {
//登录要干什么?
//1。获取用户名
String userName = loginTxtName.getText();
try {
//将用户名发送过去了
bos.write(userName.getBytes());
bos.flush();
//获取反馈信息
byte[] tong = new byte[1024];
int len = bis.read(tong);
String msg = new String(tong,0,len);
if(Constant.SUCCESS_MSG.equals(msg)){
loginSuccess();
}else {
loginFail();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//登陆成功方法
private void loginSuccess() {
mainFrame.setVisible(true);
loginFrame.setVisible(false);
loginTxtName.setText("");
//登录成功,处于聊天界面,需要一直监听读,所以需要一个线程
//因为显式消息需要用到mainShowTalk,所以要传到线程里
new Thread(new ClientThread(bis,mainShowTalk)).start();
}
//登录失败方法
private void loginFail(){
loginlabShowMsg.setText("名字重复,隐姓埋名吧");
}
//初始化ui
private void createUI() {
loginFrame = new JFrame();
this.initializeLoginFrame();
loginFrame.setLocationRelativeTo(null);
loginFrame.setVisible(true);
mainFrame = new JFrame();
this.initializeMainFrame();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(false);
}
// 客户端 启动方法
public void start() {
// 1、画界面
this.createUI();
// 2 、连接服务器并初始化io
this.connect();
// 3 、初始化 IO
//this.initIO();
//4.获取closeId
this.getCloseId();
}
private void getCloseId() {
byte[] tong = new byte[1024];
try {
int len = bis.read(tong);
colseId = new String(tong,0,len);
} catch (IOException e) {
e.printStackTrace();
}
}
//客户端连接服务端
private void connect() {
try {
Socket socket = new Socket(Constant.IP, Constant.PORT);
bos = new BufferedOutputStream(socket.getOutputStream());
bis = new BufferedInputStream(socket.getInputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
}package demo.client;
import java.awt.*;
import java.io.BufferedInputStream;
import java.io.IOException;
public class ClientThread implements Runnable {
private BufferedInputStream bis;
private TextArea mainShowTalk;
public ClientThread(BufferedInputStream bis, TextArea mainShowTalk) {
this.bis = bis;
this.mainShowTalk = mainShowTalk;
}
@Override
public void run() {
byte[] tong = new byte[1024];
int len;
while (true){
try {
len = bis.read(tong);
String msg = new String(tong,0,len);
mainShowTalk.append(msg+"\n");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Server
package demo.server;
import demo.common.Constant;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
public class Server {
//所有的客户端
private Map<String, Socket> clients = new HashMap<>();
public void start(){
//启动一个服务段,然后,等待客户端连接
try {
ServerSocket serverSocket = new ServerSocket(Constant.PORT);
System.out.println("服务端已启动,等待客户端连接");
while (true){
//服务端已启动,等待客户端连接
Socket accept = serverSocket.accept();
//启用一个线程,一直读客户端的数据
new Thread(new ServerThread(accept,clients)).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package demo.server;
import demo.common.Constant;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Map;
import java.util.UUID;
public class ServerThread implements Runnable {
private Socket socket;
private BufferedInputStream bis;
private BufferedOutputStream bos;
private Map<String, Socket> clients;
private Boolean flag = true;
public ServerThread(Socket socket,Map<String, Socket> clients) {
this.socket = socket;
this.clients = clients;
//初始化流
try {
bis = new BufferedInputStream(socket.getInputStream());
bos = new BufferedOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
//一直读客户端发送的数据,需要输入流
int len;
byte[] tong = new byte[1024];
while (flag){
try {
//发送一个随机数给我们的客户端
String closeId = UUID.randomUUID().toString();
bos.write(closeId.getBytes());
bos.flush();
String userName;
//读用户名
while (true){
len = bis.read(tong);
userName = new String(tong, 0, len);
//如果是closeId怎么办?
if(userName.equals(closeId)){
this.close();
}
if(clients.get(userName)==null){
//这个名字不重复
clients.put(userName,this.socket);
//根据用户名反馈信息给客户端 id:ahabba name:123
bos.write(Constant.SUCCESS_MSG.getBytes());
bos.flush();
//输出进入房间信息 欢迎张三进入聊天室
sendAll("欢迎"+userName+"进入聊天室");
break;
}else{
//名字重复
bos.write(Constant.FAIL_MSG.getBytes());
bos.flush();
}
}
//读消息
while (true){
len = bis.read(tong);
String input = new String(tong,0,len);
if(input.equals(closeId)){
clients.remove(userName);
sendAll(userName+"退出聊天室");
this.close();
break;
}else{
sendAll(userName+": "+input);
}
}
} catch (Exception e) {
}
}
}
private void close() {
this.flag = false;
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendAll(String string) {
BufferedOutputStream bos;
for(Socket socket : clients.values()){
try {
bos = new BufferedOutputStream(socket.getOutputStream());
bos.write(string.getBytes());
bos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Common
package demo.common;
public interface Constant {
String IP = “127.0.0.1”;
Integer PORT = 8888;
String SUCCESS_MSG = "成功123123";
String FAIL_MSG = "SHIB";
}
main
package demo.main;
import demo.client.Client;
public class StartClient {
public static void main(String[] args) {
new Client().start();
//实时打印同时在线用户(包括用户名和数量)
}
}
package demo.main;
import demo.server.Server;
public class StartServer {
public static void main(String[] args) {
new Server().start();
}
}