这是前段时间写的一个局域网多对多聊天系统,使用socket编程和TCP/IP协议进行数据传输。总体就两个部分,一个是客户端,还有一个是服务器端。其实这个系统编写起来还是很容易的。我这个小程序:
1、有一个登陆界面;
2、登陆之后进入聊天界面后会有一个服务器的欢迎语句。
在这里给出程序的源代码。
package org.zsl.server;
//服务器部分
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.util.ArrayList;
import java.util.Date;
import java.util.List;
/*
* ChatServer类 服务器
* main() 启动程序入口
* start1() 启动服务器,无线循环等待客户端
*
* ServerThread类 实现了Runnable接口
* ServerThread(Socket s) 构造方法
* send() 发送数据给客户端
* run() 覆写方法,接收数据并发送给所有的客户端
* */
public class ChatServer {
private static boolean isRun = false; //标识符
private ServerSocket serverSocket = null; //服务器
private Socket client = null;
private String name = null;
List st = new ArrayList(); //st集合用来装产生的服务器线程
public static void main(String[] args) { //启动方法
System.out.println("服务器启动!");
new ChatServer().start1();
}
private void start1() {
try {
serverSocket = new ServerSocket(8888); //实例化服务器,开启端口
isRun = true; //改变标识符
} catch (BindException e) {
System.out.println("端口使用中");
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
}
try {
while (isRun) { //无限循环
client = serverSocket.accept(); //等待客户端连接,阻塞
ServerThread serverThread = new ServerThread(client); //一个客户端连接产生了一个服务器的线程
st.add(serverThread); //将线程加入结合
name = serverThread.dis.readUTF();
serverThread.setName(name);
new Thread(serverThread).start(); //启动线程
for (int i = 0; i < st.size(); i++) { //遍历所有的线程
ServerThread temp = st.get(i);
temp.send("<服务器> 欢迎 "+this.name+" 进入聊天室!\n"); //向所有的线程发送信息
}
// dis.close();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
serverSocket.close(); //关闭服务器
} catch (IOException e) {
e.printStackTrace();
}
}
}
class ServerThread implements Runnable {
private Socket client; //定义客户端
private DataInputStream dis = null; //定义输入流
private DataOutputStream dos = null; //定义输出流
private boolean bConnected = false; //定义标志位
private boolean flag = true;
private String name = null; //定义用户姓名
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ServerThread(Socket s) {
this.client = 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 (IOException e) {
st.remove(this);
}
}
@Override
public void run() {
try {
while (bConnected) {
String str = dis.readUTF();
for (int i = 0; i < st.size(); i++) { //遍历所有的线程
ServerThread temp = st.get(i);
temp.send("<"+this.name+" "+new Date()+">\n"+" "+str); //向所有的线程发送信息
}
}
} catch (EOFException e) {
System.out.println("client closed");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (client != null) {
client.close();
client = null;
}
if (dis != null)
dis.close();
if (dos != null)
dos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
}
package org.zsl.client;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
//登陆界面
public class Register {
private JFrame frame = new JFrame("聊天系统登陆界面");
private JLabel lab = new JLabel("请输入姓名:",JLabel.CENTER);
private JTextField name = new JTextField();
private JButton submit=new JButton("登陆");
private JButton reset=new JButton("重置");
private String c_name = null;
public String getName(){ //取得用户注册姓名
return c_name;
}
public Register(){
submit.addActionListener(new ActionListener(){ //采用匿名内部类,注册submit的事件监听
public void actionPerformed(ActionEvent arg0){
if(arg0.getSource()==submit){ //判断触发源是否是提交按钮
c_name=name.getText();
new ChatClient(c_name); //将c_name传递到了ChatClient中
frame.dispose(); //关闭本窗口
}
}
});
reset.addActionListener(new ActionListener(){//注册reset的时间监听
public void actionPerformed(ActionEvent arg1){
if(arg1.getSource()==reset){//这个按钮没有反应
name.setText("");
}
}
});
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent arg0){
System.exit(1);
}
});
frame.setLayout(null);
lab.setBounds(25, 50, 100, 50);
name.setBounds(135, 60, 150, 30);
submit.setBounds(75, 120, 80, 30);
reset.setBounds(190, 120, 80, 30);
frame.add(lab);
frame.add(name);
frame.add(submit);
frame.add(reset);
int width = 350;
int high = 240;
int w = (Toolkit.getDefaultToolkit().getScreenSize().width - width) / 2;
int h = (Toolkit.getDefaultToolkit().getScreenSize().height - high) / 2;
frame.setSize(width, high);
frame.setLocation(w, h);
frame.setVisible(true);
}
public static void main(String[] args) {
new Register();
}
}
package org.zsl.client; //客户端部分 import java.awt.Frame; import java.awt.TextArea; import java.awt.TextField; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.EOFException; import java.io.IOException; import java.net.Socket; import java.net.SocketException; import java.net.UnknownHostException; import javax.swing.JButton; import javax.swing.JPanel; public class ChatClient extends Frame { Socket socket = null; TextField inputChat = new TextField(); // 定义文本框用来输入数据 TextArea showChat = new TextArea(); // 展示数据的地方 JButton submit = new JButton("发送"); JPanel pan = new JPanel(); DataInputStream dis = null; // 接收流 DataOutputStream dos = null; // 输出流 private String c_name = null; private static boolean isRun = false; private boolean flag = true; // 让c_name的传递只有一次 public ChatClient() { } public static void main(String[] args) { new ChatClient().launchFrame(); } public ChatClient(String name) { this.c_name = name; this.launchFrame(); } public void launchFrame() { // Swing 界面 this.setTitle("局域网聊天系统"); int width = 510; int high = 360; this.setLayout(null); this.setSize(width, high); showChat.setBounds(5, 5, 490, 295); pan.setBounds(5, 305, 490, 45); pan.setLayout(null); inputChat.setBounds(5, 5, 400, 40); submit.setBounds(405, 5, 95, 40); // 居中地位 int w = (Toolkit.getDefaultToolkit().getScreenSize().width - width) / 2; int h = (Toolkit.getDefaultToolkit().getScreenSize().height - high) / 2; pan.add(inputChat); pan.add(submit); this.add(showChat); this.add(pan); this.setLocation(w, h); this.setVisible(true); addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { disconnect(); System.exit(0); } }); inputChat.addActionListener(new TextFieldListener()); // 输入窗口中添加监听 submit.addActionListener(new TextFieldListener()); // 输入窗口中添加监听 connectToServer(); // 连接服务器 Thread clientThread = new Thread(new ClientThread()); clientThread.start(); // 启动客户端线程 } private void connectToServer() { try { socket = new Socket("125.221.225.105", 8888); dis = new DataInputStream(socket.getInputStream()); dos = new DataOutputStream(socket.getOutputStream()); isRun = true; } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public void disconnect() { // 如果没连接上服务器则关闭输入输出流和客户端套接字 // 关闭各种流之前必须先关闭接受线程 try { if (dos != null) { dos.close(); } if (dis != null) { dis.close(); } if (socket != null) { socket.close(); } } catch (IOException e) { e.printStackTrace(); } } private class ClientThread implements Runnable { @Override public void run() { try { if (flag) { // 启动客户端只传递一次姓名 dos.writeUTF(c_name); flag = false; } while (isRun) { // 无线循环 String str = dis.readUTF(); // 取得服务器端发送的消息 // System.out.println(str); // showChat中的部分由以前的 和 现在的组成 showChat.setText(showChat.getText() + str + '\n'); // 在showChat中显示 } } catch (SocketException e) { System.out.println("bye"); } catch (EOFException e) { } catch (IOException e) { e.printStackTrace(); } } } private class TextFieldListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { String s = inputChat.getText().trim(); if (e.getSource() == submit) { if(!("".equals(s))){ // showChat.setText(s); inputChat.setText(""); try { dos.writeUTF(s); dos.flush(); // dos.close(); } catch (IOException e1) { e1.printStackTrace(); } } } else { // showChat.setText(s); inputChat.setText(""); try { dos.writeUTF(s); dos.flush(); // dos.close(); } catch (IOException e1) { e1.printStackTrace(); } } } } }