java socket 之 简单聊天程序
这两天一直在学习java中的socket。前几天学习了一个简单的聊天程序,我尝试着自己写了一个具有可视化界面的版本,用到了简单的多线程,但是服务器端只能接受单一客户端,还没有做到接受多个客户端。另外,在聊天的信息显示上还不够完美,比较粗糙,希望大家多多指教!
下面就是原码:
服务器端:
package Chat;
import javax.swing.JFrame;
import java.awt.Dimension;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
//import java.net.ServerSocket;
//import java.net.Socket;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;public class Server extends JFrame implements Runnable{
private JPanel jServerPanel = null;
private JLabel jPortLabel = null;
private JTextField jPortTextField = null;
private JButton jConnButton = null;
private JButton jDisConnButton = null;
private JLabel jSendLabel = null;
private JScrollPane jSendScrollPane = null;
private JLabel jReceivedLabel = null;
private JScrollPane jReceivedScrollPane = null;
private JTextArea jSendTextArea = null;
private JTextArea jReceivedTextArea = null;
private JButton jSendButton = null;
private JButton jClearButton = null;
private JLabel jStateLabel = null;
private JTextField jStateTextField = null;
private ServerSocket server;
private Socket socket = null;
private boolean conState=false;
private Thread chatThread;
private PrintWriter out;
private BufferedReader in=null;
private boolean runState; /**
* This method initializes
*
*/
public Server() {
super();
initialize();
this.setLocation(200, 100);
this.setVisible(true);
} /**
* This method initializes this
*
*/
private void initialize() {
this.setSize(new Dimension(417, 375));
this.setContentPane(getJServerPanel());
this.setTitle("通信系统服务器端");
} /**
* This method initializes jServerPanel
*
* @return javax.swing.JPanel
*/
private JPanel getJServerPanel() {
if (jServerPanel == null) {
jStateLabel = new JLabel();
jStateLabel.setBounds(new Rectangle(8, 54, 65, 27));
jStateLabel.setText("系统状态:");
jReceivedLabel = new JLabel();
jReceivedLabel.setBounds(new Rectangle(11, 191, 83, 25));
jReceivedLabel.setText("信息记录:");
jSendLabel = new JLabel();
jSendLabel.setBounds(new Rectangle(9, 95, 78, 24));
jSendLabel.setText("发送信息:");
jPortLabel = new JLabel();
jPortLabel.setBounds(new Rectangle(8, 21, 64, 27));
jPortLabel.setText("端口号:");
jServerPanel = new JPanel();
jServerPanel.setLayout(null);
jServerPanel.add(jPortLabel, null);
jServerPanel.add(getJPortTextField(), null);
jServerPanel.add(getJConnButton(), null);
jServerPanel.add(getJDisConnButton(), null);
jServerPanel.add(jSendLabel, null);
jServerPanel.add(getJSendScrollPane(), null);
jServerPanel.add(jReceivedLabel, null);
jServerPanel.add(getJReceivedScrollPane(), null);
jServerPanel.add(getJSendButton(), null);
jServerPanel.add(getJClearButton(), null);
jServerPanel.add(jStateLabel, null);
jServerPanel.add(getJStateTextField(), null);
}
return jServerPanel;
} /**
* This method initializes jPortTextField
*
* @return javax.swing.JTextField
*/
private JTextField getJPortTextField() {
if (jPortTextField == null) {
jPortTextField = new JTextField();
jPortTextField.setBounds(new Rectangle(71, 19, 108, 30));
jPortTextField.setText("30000");
}
return jPortTextField;
} /**
* This method initializes jConnButton
*
* @return javax.swing.JButton
*/
private JButton getJConnButton() {
if (jConnButton == null) {
jConnButton = new JButton();
jConnButton.setBounds(new Rectangle(195, 17, 90, 33));
jConnButton.setText("准备连接");
jConnButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
if(conState==true){
JOptionPane.showMessageDialog(jServerPanel,"清先断开连接",
"清先断开连接",JOptionPane.ERROR_MESSAGE);
}
else{
serverListen();
}
}
});
}
return jConnButton;
} /**
* This method initializes jDisConnButton
*
* @return javax.swing.JButton
*/
private JButton getJDisConnButton() {
if (jDisConnButton == null) {
jDisConnButton = new JButton();
jDisConnButton.setBounds(new Rectangle(295, 17, 90, 33));
jDisConnButton.setText("断开连接");
jDisConnButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
if(conState==false){
JOptionPane.showMessageDialog(jServerPanel,"连接还没有建立",
"连接还没有建立",JOptionPane.ERROR_MESSAGE);
}
else{
try{
// jStateTextField.setText("等待接收客户端");
// repaint();
out.println("Server exit!");
out.flush();
jReceivedTextArea.insert("/n", 0);
jReceivedTextArea.insert("Server exit!", 0);
// Thread.sleep(500);
// disConnect();
stopRun();
}catch(Exception exception){
jStateTextField.setText("无法断开连接");
}
}
}
});
}
return jDisConnButton;
} /**
* This method initializes jSendScrollPane
*
* @return javax.swing.JScrollPane
*/
private JScrollPane getJSendScrollPane() {
if (jSendScrollPane == null) {
jSendScrollPane = new JScrollPane();
jSendScrollPane.setBounds(new Rectangle(9, 119, 271, 63));
jSendScrollPane.setViewportView(getJSendTextArea());
}
return jSendScrollPane;
} /**
* This method initializes jReceivedScrollPane
*
* @return javax.swing.JScrollPane
*/
private JScrollPane getJReceivedScrollPane() {
if (jReceivedScrollPane == null) {
jReceivedScrollPane = new JScrollPane();
jReceivedScrollPane.setBounds(new Rectangle(10, 215, 381, 103));
jReceivedScrollPane.setViewportView(getJReceivedTextArea());
}
return jReceivedScrollPane;
} /**
* This method initializes jSendTextArea
*
* @return javax.swing.JTextArea
*/
private JTextArea getJSendTextArea() {
if (jSendTextArea == null) {
jSendTextArea = new JTextArea();
/*
jSendTextArea.addKeyListener(
new java.awt.event.KeyListener(){
public void keyPressed(KeyEvent e){
if(e.getKeyCode()==e.VK_ENTER){
if(jSendTextArea.getText().equals("")){
JOptionPane.showMessageDialog(jServerPanel,"输入内容为空",
"输入内容为空",JOptionPane.ERROR_MESSAGE);
}
else if(conState==true){
sendInformation();
jSendTextArea.setText("");
}
else{
JOptionPane.showMessageDialog(jServerPanel,"还没有连接客户端",
"还没有连接客户端",JOptionPane.ERROR_MESSAGE);
}
}
}
public void keyReleased(KeyEvent e){
}
public void keyTyped(KeyEvent e){
}
}
);
*/
}
return jSendTextArea;
} /**
* This method initializes jReceivedTextArea
*
* @return javax.swing.JTextArea
*/
private JTextArea getJReceivedTextArea() {
if (jReceivedTextArea == null) {
jReceivedTextArea = new JTextArea();
}
return jReceivedTextArea;
} /**
* This method initializes jSendButton
*
* @return javax.swing.JButton
*/
private JButton getJSendButton() {
if (jSendButton == null) {
jSendButton = new JButton();
jSendButton.setBounds(new Rectangle(299, 120, 70, 23));
jSendButton.setText("发送");
jSendButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
if(jSendTextArea.getText().equals("")){
JOptionPane.showMessageDialog(jServerPanel,"输入内容为空",
"输入内容为空",JOptionPane.ERROR_MESSAGE);
}
else if(conState==true){
sendInformation();
jSendTextArea.setText("");
}
else{
JOptionPane.showMessageDialog(jServerPanel,"还没有连接客户端",
"还没有连接客户端",JOptionPane.ERROR_MESSAGE);
}
}
});
}
return jSendButton;
} /**
* This method initializes jClearButton
*
* @return javax.swing.JButton
*/
private JButton getJClearButton() {
if (jClearButton == null) {
jClearButton = new JButton();
jClearButton.setBounds(new Rectangle(299, 155, 70, 23));
jClearButton.setText("清空");
jClearButton.addActionListener(
new java.awt.event.ActionListener(){
public void actionPerformed(java.awt.event.ActionEvent e){
jReceivedTextArea.setText("");
}
}
);
}
return jClearButton;
} /**
* This method initializes jStateTextField
*
* @return javax.swing.JTextField
*/
private JTextField getJStateTextField() {
if (jStateTextField == null) {
jStateTextField = new JTextField();
jStateTextField.setBounds(new Rectangle(73, 54, 312, 27));
jStateTextField.setText("准备就绪,等待接收客户端");
jStateTextField.setEditable(false);
}
return jStateTextField;
} public void run(){
String msg;
runState=true;
while(runState){
try{
msg=in.readLine();
if(msg.equals("Client exit!")){//server exit
processMsg(msg);
stopRun();//终止线程
}else if(msg!=null ){
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str =(df.format(new Date()));
processMsg("Client: "+str+"/n"+msg);
}
Thread.sleep(500);
}
catch(Exception e){
}
}
//endConnect();
try{//服务器退出关闭连接和相关的"流"
jStateTextField.setText("断开连接");
socket.close();
server.close();
in.close();
out.close();
socket=null;
server=null;
}
catch(IOException ioe){}
}
public void processMsg(String msg){//客户端处理消息
//jReceivedTextArea.append(msg);
//jReceivedTextArea.append("/n");
jReceivedTextArea.insert("/n", 0);
jReceivedTextArea.insert(msg, 0);
}
public void sendInformation(){
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str =(df.format(new Date()));
out.println(jSendTextArea.getText());
processMsg("Server: "+str+"/n"+jSendTextArea.getText());
out.flush();
}
public void stopRun(){//to stop the running thread
runState=false;
conState=false;
// disConnect();
}
/*
public void disConnect(){
try{
socket.close();
server.close();
server = null;
socket = null;
conState=false;
jStateTextField.setText("断开连接");
}catch(Exception exception){
exception.printStackTrace();
}
}
*/
public void serverListen(){
try{
// jStateTextField.setText("等待接收客户端");
// repaint();
server = new ServerSocket(Integer.parseInt(jPortTextField.getText()), 5);
socket = server.accept();
in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
out=new PrintWriter(socket.getOutputStream());
conState=true;
jStateTextField.setText("建立连接,来自:"+socket.getInetAddress().getHostAddress());
}catch(Exception exception){
exception.printStackTrace();
jStateTextField.setText("建立连接失败");
}
chatThread=new Thread(this);
chatThread.start();
// run();
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO 自动生成方法存根
Server server=new Server();
server.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}} // @jve:decl-index=0:visual-constraint="10,11"
客户端:
package Chat;
import javax.swing.JFrame;
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JPanel;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;public class Client extends JFrame implements Runnable{
private JPanel jPanel = null;
private JLabel jSetServerLabel = null;
private JTextField jServerAddressTextField = null;
private JLabel jSetPortLabel = null;
private JTextField jServerPortTextField = null;
private JButton jConnectButton = null;
private JButton jDisConnectButton = null;
private JLabel jSendLabel = null;
private JTextArea jSendTextArea = null;
private JScrollPane jSendScrollPane = null;
private JTextArea jReceivedTextArea=null;
private JLabel jReceiveLabel = null;
private JScrollPane jReceiveScrollPane = null;
private JButton jSendButton = null;
private JButton jClearButton = null;
private JLabel jStateLabel = null;
private JTextField jStateTextField = null;
private Socket clientSock;
private boolean conState=false;
private PrintWriter out;
private BufferedReader in=null;
private Thread readThread;
private boolean runState;
/**
* @param args
*/
public Client(){
super("通信系统客户端");
initialize();
//Container con=getContentPane();
}
/**
* This method initializes this
*
*/
private void initialize() {
this.setSize(new Dimension(451, 409));
this.setContentPane(getJPanel());
this.setTitle("通信系统客户端");
this.setLocation(200, 100);
this.setVisible(true);
}
/**
* This method initializes jPanel
*
* @return javax.swing.JPanel
*/
private JPanel getJPanel() {
if (jPanel == null) {
jStateLabel = new JLabel();
jStateLabel.setBounds(new Rectangle(25, 106, 78, 32));
jStateLabel.setText("系统状态:");
jReceiveLabel = new JLabel();
jReceiveLabel.setBounds(new Rectangle(25, 236, 78, 24));
jReceiveLabel.setText("信息记录:");
jSendLabel = new JLabel();
jSendLabel.setBounds(new Rectangle(24, 146, 77, 23));
jSendLabel.setText("发送信息:");
jSetPortLabel = new JLabel();
jSetPortLabel.setBounds(new Rectangle(22, 57, 126, 34));
jSetPortLabel.setText("服务器端口号:");
jSetServerLabel = new JLabel();
jSetServerLabel.setBounds(new Rectangle(22, 14, 126, 34));
jSetServerLabel.setText("服务器端IP地址:");
jPanel = new JPanel();
jPanel.setLayout(null);
jPanel.add(jSetServerLabel, null);
jPanel.add(getJServerAddressTextField(), null);
jPanel.add(jSetPortLabel, null);
jPanel.add(getJServerPortTextField(), null);
jPanel.add(getJConnectButton(), null);
jPanel.add(getJDisConnectButton(), null);
jPanel.add(jSendLabel, null);
jPanel.add(getJSendTextArea(), null);
jPanel.add(getJSendScrollPane(), null);
jPanel.add(jReceiveLabel, null);
jPanel.add(getJReceivedTextArea(), null);
jPanel.add(getJReceiveScrollPane(), null);
jPanel.add(getJSendButton(), null);
jPanel.add(getJClearButton(), null);
jPanel.add(jStateLabel, null);
jPanel.add(getJStateTextField(), null);
}
return jPanel;
}
/**
* This method initializes jServerAddressTextField
*
* @return javax.swing.JTextField
*/
private JTextField getJServerAddressTextField() {
if (jServerAddressTextField == null) {
jServerAddressTextField = new JTextField();
jServerAddressTextField.setBounds(new Rectangle(148, 14, 137, 37));
jServerAddressTextField.setText("127.0.0.1");
}
return jServerAddressTextField;
}
/**
* This method initializes jServerPortTextField
*
* @return javax.swing.JTextField
*/
private JTextField getJServerPortTextField() {
if (jServerPortTextField == null) {
jServerPortTextField = new JTextField();
jServerPortTextField.setBounds(new Rectangle(148, 56, 137, 37));
jServerPortTextField.setText("30000");
}
return jServerPortTextField;
}
/**
* This method initializes jConnectButton
*
* @return javax.swing.JButton
*/
private JButton getJConnectButton() {
if (jConnectButton == null) {
jConnectButton = new JButton();
jConnectButton.setBounds(new Rectangle(315, 14, 100, 33));
jConnectButton.setText("连接服务器");
jConnectButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
if(conState==true){
JOptionPane.showMessageDialog(jPanel,"清先断开连接",
"清先断开连接",JOptionPane.ERROR_MESSAGE);
}
else{
startConnect();
}
}
});
}
return jConnectButton;
}
/**
* This method initializes jDisConnectButton
*
* @return javax.swing.JButton
*/
private JButton getJDisConnectButton() {
if (jDisConnectButton == null) {
jDisConnectButton = new JButton();
jDisConnectButton.setBounds(new Rectangle(315, 56, 100, 33));
jDisConnectButton.setText("断开连接");
jDisConnectButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
if(conState==false){
JOptionPane.showMessageDialog(jPanel,"还没有建立连接",
"还没有建立连接",JOptionPane.ERROR_MESSAGE);
}
else{
try{
out.println("Client exit!");
out.flush();
jReceivedTextArea.insert("/n", 0);
jReceivedTextArea.insert("Client exit!", 0);
//Thread.sleep(1000);
//disConnect();
stopRun();
}catch (Exception exception){
jStateTextField.setText("无法断开连接");
}
}
}
});
}
return jDisConnectButton;
}
/**
* This method initializes jSendTextArea
*
* @return javax.swing.JTextArea
*/
private JTextArea getJSendTextArea() {
if (jSendTextArea == null) {
jSendTextArea = new JTextArea();
//jSendTextArea.setBounds(new Rectangle(222, 208, 73, 43));
/*
jSendTextArea.addKeyListener(
new java.awt.event.KeyListener(){
public void keyPressed(KeyEvent e){
if(e.getKeyCode()==e.VK_ENTER){
if(jSendTextArea.getText().equals("")){
JOptionPane.showMessageDialog(jPanel,"输入内容为空",
"输入内容为空",JOptionPane.ERROR_MESSAGE);
}
else if(conState==true){
sendInformation();
jSendTextArea.setText("");
}
else{
JOptionPane.showMessageDialog(jPanel,"还没有连接客户端",
"还没有连接客户端",JOptionPane.ERROR_MESSAGE);
}
}
}
public void keyReleased(KeyEvent e){
}
public void keyTyped(KeyEvent e){
}
}
);
*/
}
return jSendTextArea;
} private JTextArea getJReceivedTextArea(){
if (jReceivedTextArea == null) {
jReceivedTextArea = new JTextArea();
//jSendTextArea.setBounds(new Rectangle(222, 208, 73, 43));
}
return jReceivedTextArea;
}
/**
* This method initializes jSendScrollPane
*
* @return javax.swing.JScrollPane
*/
private JScrollPane getJSendScrollPane() {
if (jSendScrollPane == null) {
jSendScrollPane = new JScrollPane(jSendTextArea);
jSendScrollPane.setBounds(new Rectangle(23, 169, 279, 56));
}
return jSendScrollPane;
}
/**
* This method initializes jReceiveScrollPane
*
* @return javax.swing.JScrollPane
*/
private JScrollPane getJReceiveScrollPane() {
if (jReceiveScrollPane == null) {
jReceiveScrollPane = new JScrollPane(jReceivedTextArea);
jReceiveScrollPane.setBounds(new Rectangle(24, 260, 397, 102));
}
return jReceiveScrollPane;
}
/**
* This method initializes jSendButton
*
* @return javax.swing.JButton
*/
private JButton getJSendButton() {
if (jSendButton == null) {
jSendButton = new JButton();
jSendButton.setBounds(new Rectangle(318, 171, 75, 24));
jSendButton.setText("发送");
jSendButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
if(jSendTextArea.getText().equals("")){
JOptionPane.showMessageDialog(jPanel,"输入内容为空",
"输入内容为空",JOptionPane.ERROR_MESSAGE);
}
else if(conState==true){
sendInformation();
jSendTextArea.setText("");
}
else{
JOptionPane.showMessageDialog(jPanel,"还没有连接服务器端",
"还没有连接服务器端",JOptionPane.ERROR_MESSAGE);
}
}
});
}
return jSendButton;
}
/**
* This method initializes jClearButton
*
* @return javax.swing.JButton
*/
private JButton getJClearButton() {
if (jClearButton == null) {
jClearButton = new JButton();
jClearButton.setBounds(new Rectangle(318, 200, 75, 24));
jClearButton.setText("清空");
jClearButton.addActionListener(
new java.awt.event.ActionListener(){
public void actionPerformed(java.awt.event.ActionEvent e){
jReceivedTextArea.setText("");
}
}
);
}
return jClearButton;
}
/**
* This method initializes jStateTextField
*
* @return javax.swing.JTextField
*/
private JTextField getJStateTextField() {
if (jStateTextField == null) {
jStateTextField = new JTextField();
jStateTextField.setBounds(new Rectangle(102, 107, 315, 31));
jStateTextField.setText("准备就绪,等待连接");
jStateTextField.setEditable(false);
}
return jStateTextField;
} public void startConnect(){
try{
clientSock=new Socket(jServerAddressTextField.getText(),
Integer.parseInt(jServerPortTextField.getText()) );
jStateTextField.setText("连接服务器成功,服务器:"+jServerAddressTextField.getText());
conState=true;
in=new BufferedReader(new InputStreamReader(clientSock.getInputStream()));
out=new PrintWriter(clientSock.getOutputStream());
}catch (Exception exception){
// exception.printStackTrace();
jStateTextField.setText("连接未成功建立,请重新尝试");
conState=false;
repaint();
}
//run();
readThread=new Thread(this);
readThread.start();
} public void run(){
String msg;
runState=true;
while(runState){
try{
msg=in.readLine();
// System.out.println(msg);
if(msg.equals("Server exit!")){//server exit
processMsg(msg);
stopRun();//终止线程
}else if(msg!=null ){
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str =(df.format(new Date()));
processMsg("Server: "+str+"/n"+msg);
}
Thread.sleep(500);
}
catch(Exception e){
}
}
//System.out.println("11111111111");
//endConnect();
try{//服务器退出关闭连接和相关的"流"
// System.out.println("11111111111");
jStateTextField.setText("断开连接");
clientSock.close();
clientSock=null;
conState=false;
in.close();
out.close();
}
catch(IOException ioe){}
}
public void processMsg(String msg){//客户端处理消息
//jReceivedTextArea.append(msg);
//jReceivedTextArea.append("/n");
jReceivedTextArea.insert("/n", 0);
jReceivedTextArea.insert(msg, 0);
}
public void sendInformation(){
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str =(df.format(new Date()));
out.println(jSendTextArea.getText());
processMsg("clent: "+str+"/n"+jSendTextArea.getText());
out.flush();
}
public void stopRun(){//to stop the running thread
runState=false;
conState=false;
// disConnect();
} /*
public void disConnect(){
try{
jStateTextField.setText("断开连接");
clientSock.close();
clientSock=null;
conState=false;
}catch (Exception exception){
jStateTextField.setText("无法断开连接");
}
}
*/
public static void main(String[] args) {
// TODO 自动生成方法存根
Client client=new Client();
client.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}} // @jve:decl-index=0:visual-constraint="10,10"
下面是程序运行界面的截图: