之前写的socket入门小例子:java socket入门小例子#入门教程,傻瓜也会#
这篇是在入门小例子上做的改进。增加了gui界面和多线程,所以现在小程序有界面啦:
除此之外呢,还在程序中增加了多线程的处理。之前的例子使用单个线程,所以客户端发送一条消息后,开始等待服务器端的回应。读服务端回应是一个blocking阻塞的方法,所以客户端在这就停住了,要确实等到服务器端的回应信息,客户端才能再输入。服务器端也是这样,向客户端发送一条信息后,开始等待客户端的回应,直到收到回应,才可以再输入信息。这明显和我们实际聊天的情况不符。现在,我们把监听通信方消息的代码放到了一个独立的线程当中,就可以做到同时发送和接收啦。
源码再此:
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class chatUI {
private static String hostIp = "localhost";
private static int port = 7777;
private static JPanel mainPanel;
private static JLabel statusBar;
private static JTextField chatLine;
private static JTextArea chatText;
private static ObjectOutputStream out;
private static ObjectInputStream in;
private static Socket socket;
private static ButtonGroup btnGroups;
private static boolean connect;
private static JButton connectBtn;
private static JButton disconnectBtn;
private static JRadioButton hostRadioButton;
private static JRadioButton guestRadioButton;
static ServerSocket server;
static JFrame frame;
static boolean isServer = false;
static JTextField ipField;
static JTextField portField;
public static void main(String[] args) {
// Status bar
statusBar = new JLabel();
statusBar.setText("Unconnected");
// Option bar
JPanel optionPanel = initOptionBar();
// Chat panel
JPanel chatPanel = new JPanel(new BorderLayout());
// Chat panel-text area
chatText = new JTextArea(10, 20);
chatText.setLineWrap(true);
// Chat panel-chat line
chatLine = new JTextField();
chatLine.setEditable(false);
chatLine.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (isServer) {
chatText.append("Server>" + chatLine.getText());
} else {
chatText.append("Client>" + chatLine.getText());
}
chatText.append("\n");
sendToServer(chatLine.getText());
chatLine.setText("");
// TODO set focus
}
});
chatPanel.add(chatLine, BorderLayout.SOUTH);
chatPanel.add(chatText, BorderLayout.CENTER);
// main panel
mainPanel = new JPanel(new BorderLayout());
mainPanel.add(statusBar, BorderLayout.SOUTH);
mainPanel.add(optionPanel, BorderLayout.WEST);
mainPanel.add(chatPanel, BorderLayout.CENTER);
// make a frame that holds panel
frame = new JFrame("Simple Socket Chat");
// set the panel
frame.setContentPane(mainPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Socket Chat");
frame.setSize(frame.getPreferredSize());
frame.setLocation(200, 200);
frame.pack();// frame's ready. Pack it for display.
frame.setVisible(true);
}
private static JPanel initRadioPanel() {
JPanel panel = new JPanel(new GridLayout(1, 2));
btnGroups = new ButtonGroup();
hostRadioButton = new JRadioButton();
hostRadioButton.setText("Host");
guestRadioButton = new JRadioButton();
guestRadioButton.setText("Guest");
hostRadioButton.setSelected(true);
btnGroups.add(guestRadioButton);
btnGroups.add(hostRadioButton);
panel.add(hostRadioButton);
panel.add(guestRadioButton);
return panel;
}
private static JPanel initOptionBar() {
connect = false;
// ip panel
JPanel ipPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
ipField = new JTextField(10);
ipField.setText(hostIp);
ipPanel.add(new JLabel("Host ip:"));
ipPanel.add(ipField);
// port panel
JPanel portPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
portField = new JTextField(10);
portField.setText("7777");
portPanel.add(new JLabel("port:"));
portPanel.add(portField);
// Host/Gusest radio buttons
JPanel radioPanel = initRadioPanel();
// buttons panel
JPanel buttonGroups = new JPanel(new GridLayout(1, 2));
connectBtn = new JButton("Connect");
connectBtn.setActionCommand("connect");
disconnectBtn = new JButton("Disconnect");
disconnectBtn.setActionCommand("disconnect");
if (!connect) {
disconnectBtn.setEnabled(false);
}
connectBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("connect")) {
if (hostRadioButton.isSelected()) {
startServer();
frame.setTitle("Server");
isServer = true;
} else {
connectToServer();
frame.setTitle("Client");
isServer = false;
}
try {
out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
in = new ObjectInputStream(socket.getInputStream());
} catch (IOException e1) {
e1.printStackTrace();
}
connect = true;
listeningResponse();
statusBar.setText("Connected!");
connectBtn.setEnabled(false);
disconnectBtn.setEnabled(true);
chatLine.setEditable(true);
ipField.setEditable(false);
portField.setEditable(false);
hostRadioButton.setEnabled(false);
guestRadioButton.setEnabled(false);
} else if (e.getActionCommand().equals("disconnect")) {
disconnect();
connect = false;
statusBar.setText("Disconnected");
connectBtn.setEnabled(true);
disconnectBtn.setEnabled(false);
chatLine.setEditable(false);
ipField.setEditable(true);
portField.setEditable(true);
hostRadioButton.setEnabled(true);
guestRadioButton.setEnabled(true);
}
}
});
buttonGroups.add(connectBtn);
buttonGroups.add(disconnectBtn);
JPanel mainPanel = new JPanel(new GridLayout(4, 1));
mainPanel.add(ipPanel);
mainPanel.add(portPanel);
mainPanel.add(radioPanel);
mainPanel.add(buttonGroups);
return mainPanel;
}
private static void disconnect() {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
if (socket != null) {
socket.close();
}
if (server != null) {
server.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void startServer() {
try {
server = new ServerSocket(7777);
socket = server.accept();
} catch (IOException e) {
e.printStackTrace();
}
}
private static boolean connectToServer() {
try {
socket = new Socket(hostIp, port);
return socket.isConnected();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
private static void listeningResponse() {
Thread listener = new Thread(new Runnable() {
@Override
public void run() {
String messageFromServer;
try {
while (socket.isConnected()) {
messageFromServer = (String) in.readObject();
if (isServer) {
chatText.append("Client>" + messageFromServer);
} else {
chatText.append("Server>" + messageFromServer);
}
chatText.append("\n");
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
});
listener.start();
}
private static void sendToServer(String text) {
try {
out.writeObject(text);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}