学习说明
Socket通信小程序
实现客户端与服务器端双向通信
要点:
网络编程一些常用函数的使用
多线程的基本使用
界面的绘制
学习资料为:《Java语言程序设计》梁勇
运行效果
服务器端
客户端
源码如下
存在的问题:通信会出现客户端向服务器端发送失灵,找了很久,不知道是啥情况
服务器端代码
public class Server extends JFrame {
private static final long serialVersionUID = 1L;
private int port = 8000;
private boolean isServerStarted = false;
private JPanel panelConfig = new JPanel(new BorderLayout(5, 5));
private JLabel jlblPort = new JLabel("Port:");
private JTextField jtfPort = new JTextField();
private JButton jbtnStart = new JButton("Start");
private JTextArea jtaMsg = new JTextArea();
private JScrollPane scrollPane = new JScrollPane(jtaMsg);
private JPanel panelSend = new JPanel(new FlowLayout());
private JLabel jlblSend = new JLabel("Say:");
private JTextField jtfSend = new JTextField(33);
private JComboBox<String> jcboClientList = new JComboBox<String>();
private JButton jbtnSend = new JButton("Say");
// 最多10个客户端
private DataInputStream[] fromClient = new DataInputStream[10];
private DataOutputStream[] toClient = new DataOutputStream[10];
public static int clientNo = 1;
private static int selectClientNo = 0;
public Server() {
panelConfig.add(jlblPort, BorderLayout.WEST);
panelConfig.add(jtfPort, BorderLayout.CENTER);
panelConfig.add(jbtnStart, BorderLayout.EAST);
panelConfig.setBorder(new TitledBorder("服务器设置"));
jtaMsg.setBorder(new LineBorder(Color.GRAY, 1));
panelSend.add(jlblSend);
panelSend.add(jtfSend);
panelSend.add(jcboClientList);
panelSend.add(jbtnSend);
JPanel panelAll = new JPanel(new BorderLayout(5, 5));
panelAll.setBorder(new EmptyBorder(10, 10, 10, 10));
panelAll.add(panelConfig, BorderLayout.NORTH);
panelAll.add(scrollPane, BorderLayout.CENTER);
panelAll.add(panelSend, BorderLayout.SOUTH);
add(panelAll);
setTitle("服务器");
setSize(600, 400);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
jbtnStart.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (!isServerStarted) {
isServerStarted = true;
Thread threadService = new Thread(new Service());
Thread threadReceive = new Thread(new ReceiveMsg());
threadService.start();
threadReceive.start();
}
}
});
jbtnSend.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
sendMsgToClient();
}
});
jcboClientList.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
selectClientNo = jcboClientList.getSelectedIndex();
}
});
}
public void sendMsgToClient() {
if(toClient != null) {
String sendMsg = jtfSend.getText().trim();
if(!sendMsg.equalsIgnoreCase("")) {
try {
toClient[selectClientNo].writeUTF("Server:" + sendMsg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private class Service implements Runnable {
@Override
public void run() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
jtaMsg.append("Server started at " + new Date() + " at " + port + "\n");
while (true && clientNo <= 10) {
Socket socket = serverSocket.accept();
jtaMsg.append("Starting thread for client " + clientNo + " at" + new Date() + "\n");
InetAddress inetAddress = socket.getInetAddress();
jtaMsg.append("Client " + clientNo + "'s host name is " + inetAddress.getHostName() + "\n");
jtaMsg.append("Client " + clientNo + "'s IP Address is " + inetAddress.getHostAddress() + "\n");
jcboClientList.addItem("Client " + clientNo);
fromClient[clientNo - 1] = new DataInputStream(socket.getInputStream());
toClient[clientNo - 1] = new DataOutputStream(socket.getOutputStream());
clientNo++;
}
} catch (IOException e) {
// 这里为了好看就不打印了
}
}
}
private class ReceiveMsg implements Runnable {
@Override
public void run() {
while (true) {
try {
for (int i = 0; i < clientNo; i++) {
if(fromClient[i] != null)
jtaMsg.append(fromClient[i].readUTF() + "\n");
}
} catch (IOException e) {
// 这里为了好看就不打印了
}
}
}
}
}
客户端代码
public class Client extends JFrame {
private static final long serialVersionUID = 1L;
private String host = "127.0.0.1";
private int port = 8000;
private boolean isServerConnected = false;
private JPanel panelConfig = new JPanel(new FlowLayout());
private JLabel jlblIP = new JLabel("Server IP:");
private JTextField jtfIP = new JTextField(14);
private JLabel jlblPort = new JLabel("Server Port:");
private JTextField jtfPort = new JTextField(14);
private JButton jbtnConnect = new JButton("Connect");
private JTextArea jtaMsg = new JTextArea();
private JScrollPane scrollPane = new JScrollPane(jtaMsg);
private JPanel panelSend = new JPanel(new BorderLayout(5, 5));
private JLabel jlblSend = new JLabel("Say:");
private JTextField jtfSend = new JTextField();
private JButton jbtnSend = new JButton("Say");
private DataInputStream fromServer = null;
private DataOutputStream toServer = null;
private int clientNo = 0;
private String sendMsg;
public Client() {
panelConfig.add(jlblIP);
panelConfig.add(jtfIP);
panelConfig.add(jlblPort);
panelConfig.add(jtfPort);
panelConfig.add(jbtnConnect);
panelConfig.setBorder(new TitledBorder("客户机设置"));
jtaMsg.setBorder(new LineBorder(Color.GRAY, 1));
jtaMsg.append("Wait to connect server\n");
panelSend.add(jlblSend, BorderLayout.WEST);
panelSend.add(jtfSend, BorderLayout.CENTER);
panelSend.add(jbtnSend, BorderLayout.EAST);
JPanel panelAll = new JPanel(new BorderLayout(5, 5));
panelAll.setBorder(new EmptyBorder(10, 10, 10, 10));
panelAll.add(panelConfig, BorderLayout.NORTH);
panelAll.add(scrollPane, BorderLayout.CENTER);
panelAll.add(panelSend, BorderLayout.SOUTH);
add(panelAll);
setTitle("客户端");
setSize(600, 400);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setVisible(true);
jbtnConnect.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String hostName = jtfIP.getText().trim();
String portName = jtfPort.getText().trim();
if(!(hostName.equalsIgnoreCase("") && portName .equalsIgnoreCase(""))) {
host = hostName;
port = Integer.parseInt(portName);
}
if (!isServerConnected) {
isServerConnected = true;
connect();
}
}
});
jbtnSend.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
sendMsgToServer();
}
});
}
public void sendMsgToServer() {
if(toServer != null) {
sendMsg = jtfSend.getText().trim();
if(!sendMsg.equalsIgnoreCase("")) {
try {
toServer.writeUTF("Client:" + clientNo + ":" + sendMsg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void connect() {
Socket socket = null;
while (socket == null) {
try {
socket = new Socket(host, port);
fromServer = new DataInputStream(socket.getInputStream());
toServer = new DataOutputStream(socket.getOutputStream());
jtaMsg.append("Connect to server " + host + port + "\n");
String firstMsg = "Client connected!";
toServer.writeUTF(firstMsg);
clientNo = Server.clientNo;
Thread thread = new Thread(new ReceiveMsg());
thread.start();
} catch (IOException e) {
if(socket != null)
jtaMsg.append(e.getMessage());
}
if(socket != null) {
jtaMsg.append("connect successfully!\n");
}
}
}
private class ReceiveMsg implements Runnable {
@Override
public void run() {
while (true) {
try {
jtaMsg.append(fromServer.readUTF() + "\n");
} catch (IOException e) {
// 这里为了好看就不打印了
}
}
}
}
}
控制界面
public class ControlWindow extends JFrame {
private static final long serialVersionUID = 1L;
private JButton jbtnShowMsg = new JButton("Show Rules");
private JButton jbtnStartServer = new JButton("Start Server");
private JButton jbtnStartClient = new JButton("Start Client");
private JButton jbtnExit = new JButton("Exit");
private boolean isServerStart = false;
public static void main(String[] args) {
JFrame frame = new ControlWindow();
frame.setTitle("Socket Chat");
frame.setSize(700, 400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public ControlWindow() {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
JTextArea jtaMsg = new JTextArea();
panel.add(jbtnShowMsg, BorderLayout.WEST);
panel.add(jbtnStartServer, BorderLayout.NORTH);
panel.add(jbtnStartClient, BorderLayout.EAST);
panel.add(jtaMsg, BorderLayout.CENTER);
panel.add(jbtnExit, BorderLayout.SOUTH);
setLayout(new BorderLayout());
add(panel, BorderLayout.CENTER);
jbtnStartClient.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new Client();
}
});
jbtnStartServer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(!isServerStart) {
new Server();
isServerStart = true;
}
}
});
jbtnExit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int select = JOptionPane.showConfirmDialog(null, "Confirm to exit?");
if(select == 0)
System.exit(0);
}
});
}
}