先放效果图:
登陆:
/**在本类109行附近调用了ChatClient类
*
*/
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.io.File;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.BorderFactory;
import javax.swing.Icon;
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.JPasswordField;
import javax.swing.JTextField;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
public class ClientLogin extends JFrame {
private JTextField nametext ;
private JPasswordField passwordtetx ;
//private Object bPanel;
public ClientLogin() {
this.init() ; //init方法初始化
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
public void init() {
this.setTitle("呆萌聊天室登陆");
this.setSize(330,230); //借用成熟美观尺寸
int y = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight() ;
int x = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth() ;
/**以上的方法要是不借助Eclipse实在是很难记住,尼玛!
*
*/
this.setLocation( (x-this.getWidth() )/2, ( y-this.getHeight() )/2 );
this.setResizable(false); //不允许用户自行更改大小
Icon icon = new ImageIcon("d:"+File.separator+"login.jpg") ;
JLabel label = new JLabel(icon) ; //设置登陆界面上边框
this.add(label,BorderLayout.NORTH) ;
JPanel mainPanel = new JPanel() ;
Border border = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED) ;
mainPanel.setBorder(BorderFactory.createTitledBorder(border,"输入登陆信息",TitledBorder.CENTER,TitledBorder.TOP)) ;
this.add(mainPanel,BorderLayout.CENTER) ; //将主面板加入frame
mainPanel.setLayout(null) ;
JLabel namelabel = new JLabel("请输入昵称") ;
namelabel.setBounds(30,30,80,22) ;
mainPanel.add(namelabel) ;
nametext = new JTextField() ;
nametext.setBounds(115,30,120,22);
mainPanel.add(nametext) ;
JLabel passwordlabel = new JLabel("请输入密码") ;
passwordlabel.setBounds(30,60,80,22);
mainPanel.add(passwordlabel) ;
passwordtetx = new JPasswordField() ;
passwordtetx.setBounds(115,60,120,22) ;
mainPanel.add(passwordtetx) ;
//接下来按钮位置排放
JPanel bPanel = new JPanel() ;
bPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)) ;
this.add(bPanel,BorderLayout.SOUTH) ;
JButton reset = new JButton("重置") ;
reset.addActionListener(new ActionListener() { //为“重置”按钮添加事件监听
public void actionPerformed(ActionEvent e) {
nametext.setText("");
passwordtetx.setText("");
}
});
bPanel.add(reset) ;
/**下面开始实现提交按钮
*
*/
JButton submit = new JButton("登陆") ;
submit.addActionListener(new LoginAction(this) ); //因为登陆相对复杂,重新为登陆写一个类
bPanel.add(submit) ;
}
/**下面开始写登陆类
*
*/
class LoginAction implements ActionListener {
private JFrame self ;
public LoginAction(JFrame self) {
this.self = self ;
}
public void actionPerformed(ActionEvent e) {
//System.out.println("用户名是:"+nametext.getText()+" 密码是:"+new String(passwordtext.getPassword())) ;
try {
//开始连接到服务器
Socket socket = new Socket("127.0.0.1",8888) ;
new ChatClient(socket,nametext.getText()) ;
//调用dispose方法关闭登陆框
self.dispose();
}catch(UnknownHostException e1) {
e1.printStackTrace();
JOptionPane.showConfirmDialog(self, "找不到指定服务器!~","连接失败",JOptionPane.OK_OPTION,JOptionPane.ERROR_MESSAGE) ;
}catch(IOException e1) {
e1.printStackTrace() ;
JOptionPane.showConfirmDialog(self, "连接服务器出错,请重试!","连接失败",JOptionPane.OK_OPTION,JOptionPane.ERROR_MESSAGE) ;
}
}
}
public static void main(String args[]) {
new ClientLogin() ;
}
}
客户端:
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Date;
import java.text.SimpleDateFormat;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
public class ChatClient extends JFrame {
private Socket socket ; //负责和服务器通信
private JTextArea sendArea ; //消息编辑区域
private JTextArea contentArea ; //群聊消息显示框
private String name ; //当前用户名称
public ChatClient(Socket socket,String name) {
this.socket = socket ;
this.name = name ;
this.init() ; //初始化聊天客户端
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
/*接下来启动单独线程,专门从服务器中读取数据
*
*/
ClientThread thread = new ClientThread(socket,contentArea) ;
thread.start();
}
public void init( ) {
this.setTitle("我的聊天室");
this.setSize(300,400);
int x = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth() ;
int y = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight() ;
this.setLocation( (x-this.getWidth() )/2, ( y-this.getHeight() )/2 );
this.setResizable(false); //不允许用户改变大小
contentArea = new JTextArea() ;
contentArea.setLineWrap(true); //换行方法
JScrollPane logPanel = new JScrollPane(contentArea,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ) ;
sendArea = new JTextArea() ;
sendArea.setLineWrap(true); //控制每行显示长度最大不超过界面长度
JScrollPane sendPanel = new JScrollPane(sendArea,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ) ;
//创建一个分隔窗格
JSplitPane splitpane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,logPanel,sendPanel) ;
splitpane.setDividerLocation(250);
this.add(splitpane,BorderLayout.CENTER) ;
//按钮面板
JPanel bPanel = new JPanel() ;
bPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)) ;
this.add(bPanel,BorderLayout.SOUTH) ;
JLabel namelabel = new JLabel("昵称: "+this.name+" ") ;
bPanel.add(namelabel) ;
JButton closeButton = new JButton("关闭") ;
closeButton.addActionListener( new ActionListener( ) {
public void actionPerformed(ActionEvent e) {
}
});
bPanel.add(closeButton) ;
JButton sendButton = new JButton("发送") ;
sendButton.addActionListener(new ActionListener() {
//@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
String str = sendArea.getText() ;
SimpleDateFormat formater = new SimpleDateFormat("HH:mm:ss") ;
String time = formater.format(new Date() ) ;
String sendStr = name+" "+time+" 说: "+str ;
PrintWriter out = null ;
try {
out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream() ) ) ;
out.println(sendStr) ;
out.flush();
}catch(Exception e1) {
e1.printStackTrace();
}
sendArea.setText("");
}
});
bPanel.add(sendButton) ;
}
}
//客户端与服务器端通信的线程类
class ClientThread extends Thread {
private Socket socket ;
private JTextArea contentArea ;
public ClientThread(Socket socket, JTextArea conteArea) {
this.socket = socket ;
this.contentArea = conteArea ;
}
public void run() {
BufferedReader br = null ;
try {
br = new BufferedReader(new InputStreamReader( socket.getInputStream())) ;
String str = null ;
while( (str = br.readLine()) != null) {
System.out.println(str) ;
contentArea.append(str);
contentArea.append("\n");
}
} catch(IOException e) {
e.printStackTrace();
} finally {
if(br != null) {
try {
br.close () ;
}catch(IOException e) {
e.printStackTrace();
}
}
}
}}
服务器端:
import java.util.List;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class ChatServer {
private List<Socket> sockets = new ArrayList<Socket>() ; //类集的应用
public ChatServer() throws IOException {
ServerSocket ss = new ServerSocket(8888) ;
System.out.println("服务器已在监听8888端口") ;
while(true) {
Socket socket = ss.accept() ;
sockets.add(socket) ;
String ip = socket.getInetAddress().getHostAddress() ;
System.out.println("新用户进入!ip是"+ip) ;
Thread thread = new Thread(new ServerRunner(sockets,socket)) ;
thread.start();
}
}
public static void main(String args[]) {
try {
new ChatServer() ;
} catch(Exception e) {
e.printStackTrace();
}
}
}
class ServerRunner implements Runnable {
private List<Socket> sockets ;
private Socket currentSocket ; //当前socket
public ServerRunner (List<Socket> sockets,Socket currentSocket) {
this.sockets = sockets ;
this.currentSocket = currentSocket ;
}
public void run() {
String ip = currentSocket.getInetAddress().getHostAddress() ;
BufferedReader br = null ;
try {
br = new BufferedReader(new InputStreamReader(currentSocket.getInputStream())) ;
String str = null ;
while((str = br.readLine()) != null) {
System.out.println(ip+"说"+str) ;
//往所有的客户端写入信息
for(Socket temp : sockets) {
PrintWriter pw = new PrintWriter(new OutputStreamWriter(temp.getOutputStream())) ;
pw.println(str) ;
pw.flush();
}
}
}catch(IOException e) {
e.printStackTrace();
}
}
}