赞
踩
这是这个网络聊天室项目的原理图:
很简单,首先ABCD是4个客户端,当A发送信息给服务器,服务器实现以广播的形式把信息全发给每个人---群发群聊
客户端代码:
package com.aa;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.*;
import java.net.*;
import java.util.Date;
import java.awt.BorderLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;
public class Client {
public static void initUIManager() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
System.err.println("获取系统外观失败:" + e);
}
}
public static void main(String[] args) {
initUIManager();
new ClientFrame();
}
}
class ClientFrame extends JFrame implements Runnable, ActionListener,
KeyListener {
private static final long serialVersionUID = 8518610966119429018L;
ImageIcon image;// 定义一个图片
JPanel panel;
JLabel label;
JFrame frame;// 改变窗体的大小
JScrollPane textPane;
JTextArea areaText;
// 加滚动轴代码
JTextField fieldMsg;
JButton butSend;
JButton butConnect;
Socket socket;
DataInputStream in;
DataOutputStream out;
Thread thread;
public static int WIDTH = 500;
public static int HEIGHT = 400;
public static String title = "Client";
private static final String IP_ADDRESS = "127.0.0.1";
public ClientFrame() {
init();
setTitle("客户端");
setSize(480, 400);//
setLocationRelativeTo(null);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}// 首先确定插入一张图片
public void init() {// /
setLayout(null);
image = new ImageIcon("90.jpg");//
label = new JLabel(image);
label.setBounds(173, 0, 415, 324);
panel = new JPanel();//
areaText = new JTextArea();
this.setResizable(false);
panel.add(areaText);
areaText.setLineWrap(true);
areaText.setEditable(false);
textPane = new JScrollPane(areaText);
// 客户端 (Client) (通常是一个采用图形用//界面的程序)与服务器 (Server) 区分开来。
butSend = new JButton("Send");
butSend.addKeyListener(this);// 设置按钮监听器
fieldMsg = new JTextField(150);
butSend.addActionListener(this);
butConnect = new JButton("Connect");
butConnect.addActionListener(this);
areaText.setBackground(Color.yellow);// /该背景色
// 设置文本区域的大小
areaText.setBounds(0, 0, 287, 321);// /修改文本域的大小
textPane.setBounds(5, 5, 475, 320);
fieldMsg.setBounds(5, 330, 280, 24);
butSend.setBounds(299, 330, 80, 24);
butConnect.setBounds(394, 330, 80, 24);
add(panel);
add(label, BorderLayout.EAST);
add(areaText);//
add(textPane);//
add(butSend);
add(butConnect);
add(fieldMsg);
Toolkit kit = Toolkit.getDefaultToolkit();
Image imge = kit.getImage("27.jpg");
this.setIconImage(imge);
fieldMsg.addKeyListener(this);
socket = new Socket();// 客户端对象
thread = new Thread(this);
}
//
public void startSocket() {// (一)核心
try {// 向服务器端发送一个连接请求,跟服务器创建一个连接
if (!socket.isConnected()) {//
InetAddress address = InetAddress.getByName(IP_ADDRESS);
InetSocketAddress socketAddress = new InetSocketAddress(// 是.net包中的一个类
address, 4339);// 根据ip地址和端口号创建套接字地址
socket.connect(socketAddress);
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
butSend.setEnabled(true);
if (!(thread.isAlive())) {
thread = new Thread(this);
}
thread.start();
}
} catch (Exception e) {
System.out.println(e);
socket = new Socket();
}
}
public void send() {
String msg = fieldMsg.getText().trim();
if (msg.isEmpty()) {
JOptionPane.showMessageDialog(this,
"Please input you message before sending.");
return;
}
// areaText.append("Client: " + msg + "\n");
fieldMsg.setText("");
try {
Date d = new Date();
out.writeUTF("\n" + msg + "\n" + d.toLocaleString());// 这是发送给服务器的
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void actionPerformed(ActionEvent arg0) {// 使用此方法判断
if (arg0.getSource() == butSend) {
send();
} else if (arg0.getSource() == butConnect) {
startSocket();
}
}
@Override
public void run() {// 这和send方法有何先后顺序,服务端程序运行后,客户端该最哪些动作,同时服务器端程序是怎样的?
if (Thread.currentThread() == thread) {
String msg = null;
while (true) {// 循环接收服务器端发送的信息并显示在文本区
try { // /核心(二)
msg = in.readUTF();//
areaText.append("Client: " + msg + "\n");// 我曾修改过
} catch (IOException e) {
e.printStackTrace();
socket = new Socket();
break;
}
}
}
}
@Override
public void keyPressed(KeyEvent arg0) {
if (arg0.getKeyCode() == KeyEvent.VK_ENTER) {
send();
}
}
@Override
public void keyReleased(KeyEvent arg0) {
}
@Override
public void keyTyped(KeyEvent arg0) {
}
}
服务器端代码:
package com.aa;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
public class Server {
boolean started = false;
ServerSocket ss = null;
List clients = new ArrayList(); // 保存客户端线程类list是一个接口,Arraylist是一个类
// ArrayList是一个集合类。类里面可以放很多对象。 clients.size是指的是有多少个对象
public static void main(String[] args) {
new Server().start();
}
void start() {
try {
ss = new ServerSocket(4339); // 建立服务端对象
started = true;
} catch (BindException e) {//创建对象后,需要做异常处理,以便程序出错时,做出响应
System.out.println("端口使用中");
} catch (IOException e) {
e.printStackTrace();//
} // 死循环
try {// 核心(一)
while (started) {
Socket s = ss.accept(); // 监听客户端发来的请求/
ChatClient c = new ChatClient(s);
System.out.println("客戶端接收成功");
new Thread(c).start();
clients.add(c);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 这个类的作用
// 建立客户端线程接收,发送数据多线程的所以要实现Runnable接口
class ChatClient implements Runnable {
private Socket s;
DataInputStream dis = null;
DataOutputStream dos = null;
boolean bConnected = false;
public ChatClient(Socket s) {
this.s = s;
try {// 用来接收客户端发来数据的输入流
dis = new DataInputStream(s.getInputStream());
// 服务器向客户端发送数据的输出流
dos = new DataOutputStream(s.getOutputStream());
bConnected = true;
} catch (IOException e) {
e.printStackTrace();
}
}
public void send(String str) {
try {
dos.writeUTF(str);// *这也是服务器发送给客户端的
} catch (SocketException e) {
System.out.println("對方退出了");//
} catch (IOException e) {
e.printStackTrace();
}
}
//
public void run() {// 核心(二) //实现接口,就必须重写接口里的方法
try {
while (bConnected) {
String str = dis.readUTF();// *是阻塞式的,没有发过来信息,就死死等着,
for (int i = 0; i < clients.size(); i++) {
ChatClient c = clients.get(i);// 服务器端获取多少个客户端与他连接,将信息发送给每一个客户端
c.send(str);//
}
}
} catch (EOFException e) {
System.out.println("客戶端退出了");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dis != null)
if (s != null)//
try {//
dis.close();
s.close();
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。