我在用java做一个简单的即时通讯工具,自学的所以很多都不会,希望可以帮帮我

2024-11-25 19:44:31
推荐回答(1个)
回答1:

package service_client_for_many;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/**
* 双工服务器,多人 本服务器默认不提供服务,而是在客户端连接时创建独立线程负责业务
**/
public class MutilServer implements ActionListener {
private JFrame frame;
/** 边界布局的主面板 */
private JPanel panelMain;
private JPanel panelDown;
private JTextArea ta;
private JTextField txt;
private JButton but;
private JScrollPane jsp;
private Font font;
/**
* 当前服务器使用端口
*/
private int port = 6666;
/**
* 远程客户端的IP
*/
private String clientIp;
/**
* 记录所有正在工作的服务员的登记表
*/
private Vector dengJiBiao;

public MutilServer() {
frame = new JFrame("双工多人服务器");
panelMain = new JPanel(new BorderLayout());
panelDown = new JPanel();
ta = new JTextArea();
txt = new JTextField(20);
but = new JButton("发送");
jsp = new JScrollPane(ta);
// 粘贴界面
panelDown.add(txt);
panelDown.add(but);
panelMain.add(jsp, BorderLayout.CENTER);
panelMain.add(panelDown, BorderLayout.SOUTH);
// 字体
font = new Font("宋体", Font.BOLD, 18);
txt.setFont(font);
ta.setFont(font);
but.setFont(font);
// 文本域只读
ta.setEditable(false);
// 按钮添加监听
but.addActionListener(this);
frame.add(panelMain);
frame.setBounds(100, 300, 400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 关闭窗体时结束程序
frame.setAlwaysOnTop(true);// 永远在所有窗体最上
frame.setVisible(true);
// 创建登记表
dengJiBiao = new Vector();
// 光标给消息文本框
txt.requestFocus();
createServer();
}

/**
* 显示文本到文本域,并且追加一个换行
*
* @param msg
* 要显示的文本
*/
public void showTxt(String msg) {
ta.append(msg + "\n");
}

public static void main(String[] args) {
new MutilServer();
}

// 动作监听
public void actionPerformed(ActionEvent e) {
if (e.getSource() == but) {// 发送
txt.requestFocus();
String str = txt.getText().trim();
if(str.length()==0){
showTxt("不可以发送空消息");
return;
}
if(dengJiBiao.size()==0){
showTxt("当前木有客户连接,无法发送信息");
return;
}
str ="服务器消息:"+str;
//找到所有登记表中的服务员,实现群发
for (int i = 0; i < dengJiBiao.size(); i++) {
Waiter w = dengJiBiao.get(i);//得到当前循环的服务员
w.send(str);
}
// 清空文本框,得到焦点
txt.setText("");
}
}

/**
* 启动网络服务器
*/
public void createServer() {
showTxt("正在启动服务器,使用本机" + port + "端口...");
try {
ServerSocket server = new ServerSocket(port);
showTxt("服务器启动成功,开始监听网络连接...");
while (true) {
Socket jiaoYi = server.accept();
// 每得到一个交易,就是来了一个客户端.需要交给一个新的服务员去维护处理
new Waiter(jiaoYi, dengJiBiao, this);
}
} catch (IOException e) {
showTxt("服务器启动失败,可能端口被占用");
}
}
}

package service_client_for_many;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/** 客户端双工 */
public class MyClient implements ActionListener{
private JFrame frame;
/** 边界布局的主面板 */
private JPanel panelMain;
private JPanel panelDown;
private JTextArea ta;
private JTextField txt;
private JButton but;
private JScrollPane jsp;
private Font font;
/**
* 服务器IP
*/
private String ip = "192.168.10.239";
/**
* 服务器端口
*/
private int port = 6666;
private BufferedReader br;
private BufferedWriter bw;
public MyClient() {
frame = new JFrame("双工客户端1");
panelMain = new JPanel(new BorderLayout());
panelDown = new JPanel();
ta = new JTextArea();
txt = new JTextField(20);
but = new JButton("发送");
jsp = new JScrollPane(ta);
// 粘贴界面
panelDown.add(txt);
panelDown.add(but);
panelMain.add(jsp, BorderLayout.CENTER);
panelMain.add(panelDown, BorderLayout.SOUTH);
// 字体
font = new Font("宋体", Font.BOLD, 18);
txt.setFont(font);
ta.setFont(font);
but.setFont(font);
// 文本域只读
ta.setEditable(false);
//按钮添加监听
but.addActionListener(this);
frame.add(panelMain);
frame.setBounds(500, 200, 400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 关闭窗体时结束程序
frame.setAlwaysOnTop(true);// 永远在所有窗体最上
frame.setVisible(true);
// 光标给消息文本框
txt.requestFocus();
linkServer();
}
/** 显示文本到文本域,并且追加一个换行
* @param msg 要显示的文本
*/
public void showTxt(String msg) {
ta.append(msg+"\n");
}

public static void main(String[] args) {
new MyClient();
}
//动作监听
public void actionPerformed(ActionEvent e) {
if (e.getSource() == but) {// 发送
if (bw == null) {
showTxt("当前没有客户端连接,无法发送消息");
return;
}
String s = txt.getText().trim();// 得到文本框要发送的文字,去掉两端空格
if (s.length() == 0) {
showTxt("不可以发送空消息");
return;
}
showTxt("我说:" + s);
try {
bw.write(s + "\n");// 发送网络消息给对方
bw.flush();// 清空缓冲
} catch (IOException e1) {
showTxt("信息:" + s + " 发送失败");
}
// 清空文本框,得到焦点
txt.setText("");
txt.requestFocus();
}
}
/**
* 连接服务器
*/
public void linkServer(){
showTxt("准备连接服务器"+ip+":"+port);
try {
Socket jiaoYi = new Socket(ip,port);
showTxt("连接服务器成功,开始进行通讯");
// 得到输入和输出
br = new BufferedReader(new InputStreamReader(
jiaoYi.getInputStream()));
bw = new BufferedWriter(new OutputStreamWriter(
jiaoYi.getOutputStream()));
String s = null;
while ((s = br.readLine()) != null) {
showTxt( s);
}
} catch (UnknownHostException e) {
showTxt("连接服务器失败,网络连通错误");
} catch (IOException e) {
showTxt("与服务器通讯失败,已经断开连接");
}
showTxt("关闭");
}
}

package service_client_for_many;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/** 客户端双工 */
public class MyClient2 implements ActionListener{
private JFrame frame;
/** 边界布局的主面板 */
private JPanel panelMain;
private JPanel panelDown;
private JTextArea ta;
private JTextField txt;
private JButton but;
private JScrollPane jsp;
private Font font;
/**
* 服务器IP
*/
private String ip = "192.168.10.239";
/**
* 服务器端口
*/
private int port = 6666;
private BufferedReader br;
private BufferedWriter bw;
public MyClient2() {
frame = new JFrame("双工客户端2");
panelMain = new JPanel(new BorderLayout());
panelDown = new JPanel();
ta = new JTextArea();
txt = new JTextField(20);
but = new JButton("发送");
jsp = new JScrollPane(ta);
// 粘贴界面
panelDown.add(txt);
panelDown.add(but);
panelMain.add(jsp, BorderLayout.CENTER);
panelMain.add(panelDown, BorderLayout.SOUTH);
// 字体
font = new Font("宋体", Font.BOLD, 18);
txt.setFont(font);
ta.setFont(font);
but.setFont(font);
// 文本域只读
ta.setEditable(false);
//按钮添加监听
but.addActionListener(this);
frame.add(panelMain);
frame.setBounds(900, 200, 400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 关闭窗体时结束程序
frame.setAlwaysOnTop(true);// 永远在所有窗体最上
frame.setVisible(true);
// 光标给消息文本框
txt.requestFocus();
linkServer();
}
/** 显示文本到文本域,并且追加一个换行
* @param msg 要显示的文本
*/
public void showTxt(String msg) {
ta.append(msg+"\n");
}

public static void main(String[] args) {
new MyClient2();
}
//动作监听
public void actionPerformed(ActionEvent e) {
if (e.getSource() == but) {// 发送
if (bw == null) {
showTxt("当前没有客户端连接,无法发送消息");
return;
}
String s = txt.getText().trim();// 得到文本框要发送的文字,去掉两端空格
if (s.length() == 0) {
showTxt("不可以发送空消息");
return;
}
showTxt("我说:" + s);
try {
bw.write(s + "\n");// 发送网络消息给对方
bw.flush();// 清空缓冲
} catch (IOException e1) {
showTxt("信息:" + s + " 发送失败");
}
// 清空文本框,得到焦点
txt.setText("");
txt.requestFocus();
}
}
/**
* 连接服务器
*/
public void linkServer(){
showTxt("准备连接服务器"+ip+":"+port);
try {
Socket jiaoYi = new Socket(ip,port);
showTxt("连接服务器成功,开始进行通讯");
// 得到输入和输出
br = new BufferedReader(new InputStreamReader(
jiaoYi.getInputStream()));
bw = new BufferedWriter(new OutputStreamWriter(
jiaoYi.getOutputStream()));
String s = null;
while ((s = br.readLine()) != null) {
showTxt(s);
}
} catch (UnknownHostException e) {
showTxt("连接服务器失败,网络连通错误");
} catch (IOException e) {
showTxt("与服务器通讯失败,已经断开连接");
}
showTxt("关闭");
}
}

package service_client_for_many;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Vector;

/**
* 服务员,线程类
* 在客户端连接后创建启动
* 负责当前客户端的所有数据收发
* 并且在业务需要时,将结果与服务器(老板)进行报告
*/
public class Waiter extends Thread{
private Socket sc;
private Vector dengJiBiao ;
private MutilServer server;
/**
* 客户端IP
*/
private String ip;
private BufferedReader br;
private BufferedWriter bw;
/** 创建一个的新的服务员,负责当前传递的客户端连接(交易)
* 启动新线程
* @param sc 负责的交易
* @param dengJiBiao所有正在工作的服务员(所有交易)
* @param server 老板,也就是服务器
*/
public Waiter(Socket sc, Vector dengJiBiao,
MutilServer server) {
this.sc = sc;
this.dengJiBiao = dengJiBiao;
this.server = server;
//初始化连接的准备工作
ip = sc.getInetAddress().getHostAddress();
// 得到输入和输出
try {
br = new BufferedReader(new InputStreamReader(
sc.getInputStream()));
bw = new BufferedWriter(new OutputStreamWriter(
sc.getOutputStream()));
} catch (IOException e) {
this.server.showTxt("与客户端:"+ip+"建立通讯失败");
e.printStackTrace();
return;//无效客户,不再继续
}
this.server.showTxt("客户端:"+ip+"连接服务器成功");
//启动线程
this.start();
}
//线程
public void run(){
//开始时,登记开工
dengJiBiao.addElement(this);
System.out.println(this.getClass().getName());
try {
String s = null;
while ((s = br.readLine()) != null) {
server.showTxt("客户"+ip+"说:" + s);
//当前客户发来的信息,其它客户也要能看得见.需要实现转发
//从登记表找到所有正在干活的服务员
for (int i = 0; i < dengJiBiao.size(); i++) {
Waiter w = dengJiBiao.get(i);
//排除掉当前服务员自己
if(w!=this)
w.send("客户"+ip+"说:" + s);
}
}
} catch (Exception e) {
server.showTxt("客户"+ip+"已经离开");
}
//结束时,登记下班
dengJiBiao.removeElement(this);
}

/** 发送信息给当前服务员负责的客户端
* @param msg
*/
public void send(String msg){
try {
bw.write(msg+"\n");
bw.flush();
} catch (Exception e) {
server.showTxt("给客户:"+ip+"发送信息"+msg+"失败");
}
}
}

一个服务器类·两个客户端类,一个线程类负责收发