This is a few years ago , An interview question from Sina ~ The requirement is 3 Within days ~
adopt TCP agreement , Build a server side .
Server side configuration IP And port :
Clients can communicate with each other ~
Once online, all online users will receive your online notification .
After offline, all online users will receive your offline notification !
You can talk in private , You can group chat .
This is the first version ~ You can add more functions when you are free ~ For example, sending files ~ wait ~
The design idea is as follows :
On the server side Use one HashMap< userName,socket> Maintain all user related information , So as to ensure communication with all users .
Client actions :
(1) Connect ( Sign in ): send out userName Corresponding actions of the server :1) Interface display ,2) Inform other users about your login information , 3) Put other online users userName Notify the current user 4) Start a thread to serve the current thread
(2) sign out ( Cancellation ):
(3) Send a message
※※ After sending the communication content , How does the other person know what to do , Through message protocol :
The format design of the message sent by the client to the server :
Command key @# The receiving party @# The message content @# The sender
1) Connect :userName —- Handshake thread serverSocket Receive this message exclusively , Others are newly opened by the server to communicate with customers socket To receive
2) sign out :[email protected]# All @#[email protected]#userName
3) send out : on @# JList.getSelectedValue() @# tfdMsg.getText() @# tfdUserName.getText()
The format design of the message sent by the server to the client :
Command key @# The sender @# The message content
Sign in :
1) msg @#server @# user [userName] Log on to the ( Display to the client )
2) [email protected]#server @# userName ( For the client to maintain the online user list )
sign out :
1) msg @#server @# user [userName] Out of the ( Display to the client )
2) [email protected]#server @# userName ( For the client to maintain the online user list )
send out :
msg @# Message sender ( msgs[3] ) @# The message content (msgs[2])
Server side source code :
package cn.hncu;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Scanner;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
/**
* The server
*
* @author Chen Haoxiang
*
* @version 1.0 2016-5-13
*/
public class ServerForm extends JFrame {
private JList<String> list;
private JTextArea area;
private DefaultListModel<String> lm;
public ServerForm() {
JPanel p = new JPanel(new BorderLayout());
// The rightmost user online list
lm = new DefaultListModel<String>();
list = new JList<String>(lm);
JScrollPane js = new JScrollPane(list);
Border border = new TitledBorder(" On-line ");
js.setBorder(border);
Dimension d = new Dimension(100, p.getHeight());
js.setPreferredSize(d);// Set location
p.add(js, BorderLayout.EAST);
// Notification text area
area = new JTextArea();
//area.setEnabled(false);// Cannot select and modify
area.setEditable(false);
p.add(new JScrollPane(area), BorderLayout.CENTER);
this.getContentPane().add(p);
// Add menu item
JMenuBar bar = new JMenuBar();// Menu bar
this.setJMenuBar(bar);
JMenu jm = new JMenu(" control (C)");
jm.setMnemonic('C');// Set mnemonics ---Alt+'C', Show it , But don't run
bar.add(jm);
final JMenuItem jmi1 = new JMenuItem(" Turn on ");
jmi1.setAccelerator(KeyStroke.getKeyStroke('R', KeyEvent.CTRL_MASK));// Set shortcut key Ctrl+'R'
jmi1.setActionCommand("run");
jm.add(jmi1);
JMenuItem jmi2 = new JMenuItem(" sign out ");
jmi2.setAccelerator(KeyStroke.getKeyStroke('E', KeyEvent.CTRL_MASK));// Set shortcut key Ctrl+'R'
jmi2.setActionCommand("exit");
jm.add(jmi2);
// monitor
ActionListener a1 = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("run")) {
startServer();
jmi1.setEnabled(false);// Internal methods ~ Access can only be final object
} else {
System.exit(0);
}
}
};
jmi1.addActionListener(a1);
Toolkit tk = Toolkit.getDefaultToolkit();
int width = (int) tk.getScreenSize().getWidth();
int height = (int) tk.getScreenSize().getHeight();
this.setBounds(width / 4, height / 4, width / 2, height / 2);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);// Turn off the function of the button
setVisible(true);
}
private static final int PORT = 9090;
protected void startServer() {
try {
ServerSocket server = new ServerSocket(PORT);
area.append(" Start the service :" + server);
new ServerThread(server).start();
} catch (IOException e) {
e.printStackTrace();
}
}
// Used to save the names and of all online users Socket---- pool
private Map<String, Socket> usersMap = new HashMap<String, Socket>();
class ServerThread extends Thread {
private ServerSocket server;
public ServerThread(ServerSocket server) {
this.server = server;
}
@Override
public void run() {
try {// Shake hands with the client
while (true) {
Socket socketClient = server.accept();
Scanner sc = new Scanner(socketClient.getInputStream());
if (sc.hasNext()) {
String userName = sc.nextLine();
area.append("\r\n user [ " + userName + " ] Sign in " + socketClient);// Notify on the client side
lm.addElement(userName);// Add to user online list
new ClientThread(socketClient).start();// Specifically for this client
usersMap.put(userName, socketClient);// Add the currently logged in user to “ Online users ” In the pool
msgAll(userName);// hold “ The message that the current user logs in is the user name ” Notify all others who are already online
msgSelf(socketClient);// Notify the currently logged in user , Information about other people online
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class ClientThread extends Thread {
private Socket socketClient;
public ClientThread(Socket socketClient) {
this.socketClient = socketClient;
}
@Override
public void run() {
System.out.println(" A thread that communicates with the client starts and starts communicating ...");
try {
Scanner sc = new Scanner(socketClient.getInputStream());
while (sc.hasNext()) {
String msg = sc.nextLine();
System.out.println(msg);
String msgs[] = msg.split("@#@#");
// Black proof
if(msgs.length!=4){
System.out.println(" The black ones ...");
continue;
}
if("on".equals(msgs[0])){
sendMsgToSb(msgs);
}
if("exit".equals(msgs[0])){
// The server shows
area.append("\r\n user [ " + msgs[3] + " ] Exited !" + usersMap.get(msgs[3]));
// Delete the user from the online user pool
usersMap.remove(msgs[3]);
// Delete the user from the online list of the server
lm.removeElement(msgs[3]);
// Notify other users , The user has exited
sendExitMsgToAll(msgs);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// Notify other users . The user has exited
private void sendExitMsgToAll(String[] msgs) throws IOException {
Iterator<String> userNames = usersMap.keySet().iterator();
while(userNames.hasNext()){
String userName = userNames.next();
Socket s = usersMap.get(userName);
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
String str = "[email protected]#@#[email protected]#@# user [ "+msgs[3]+" ] Exited !";
pw.println(str);
pw.flush();
str = "[email protected]#@#[email protected]#@#"+msgs[3];
pw.println(str);
pw.flush();
}
}
// The server forwards the chat message of the client to the corresponding other clients
public void sendMsgToSb(String[] msgs) throws IOException {
if(" All ".equals(msgs[1])){
Iterator<String> userNames = usersMap.keySet().iterator();
// Traverse every online user , Send him the chat message
while(userNames.hasNext()){
String userName = userNames.next();
Socket s = usersMap.get(userName);
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
String str = "[email protected]#@#"+msgs[3]+"@#@#"+msgs[2];
pw.println(str);
pw.flush();
}
}else{
Socket s = usersMap.get(msgs[1]);
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
String str = "[email protected]#@#"+msgs[3]+" For you @#@#"+msgs[2];
pw.println(str);
pw.flush();
}
}
/**
* hold “ The message that the current user logs in is the user name ” Notify all others who are already online
*
* @param userName
*/
// Technical thinking : Take each in turn from the pool socket( On behalf of every online user ) Take out , Send it userName
public void msgAll(String userName) {
Iterator<Socket> it = usersMap.values().iterator();
while (it.hasNext()) {
Socket s = it.next();
try {
PrintWriter pw = new PrintWriter(s.getOutputStream(), true);// Add true For automatic refresh
String msg = "[email protected]#@#[email protected]#@# user [ " + userName + " ] Logged in !";// Notify the client to display a message
pw.println(msg);
pw.flush();
msg = "[email protected]#@#[email protected]#@#" + userName;// Notify the client to add users to the online list .
pw.println(msg);
pw.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Notify the currently logged in user , Information about other people online
*
* @param socketClient
*/
// Send the names of those users who are already online to the login user , Let him give his interface lm Add the corresponding user name
public void msgSelf(Socket socketClient) {
try {
PrintWriter pw = new PrintWriter(socketClient.getOutputStream(),true);
Iterator<String> it = usersMap.keySet().iterator();
while (it.hasNext()) {
String msg = "[email protected]#@#[email protected]#@#" + it.next();
pw.println(msg);
pw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
JFrame.setDefaultLookAndFeelDecorated(true);// Set decoration
new ServerForm();
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
- 248.
- 249.
- 250.
- 251.
- 252.
- 253.
- 254.
- 255.
- 256.
- 257.
- 258.
- 259.
- 260.
- 261.
- 262.
- 263.
- 264.
- 265.
- 266.
- 267.
- 268.
- 269.
- 270.
- 271.
- 272.
- 273.
- 274.
- 275.
- 276.
- 277.
- 278.
- 279.
- 280.
- 281.
- 282.
- 283.
- 284.
- 285.
- 286.
- 287.
- 288.
- 289.
- 290.
- 291.
- 292.
- 293.
- 294.
- 295.
- 296.
- 297.
- 298.
- 299.
- 300.
Client source code :
package cn.hncu;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
/**
* client
*
* @author Chen Haoxiang
* @version 1.0 2016-5-13
*/
public class ClientForm extends JFrame implements ActionListener {
private JTextField tfdUserName;
private JList<String> list;
private DefaultListModel<String> lm;
private JTextArea allMsg;
private JTextField tfdMsg;
private JButton btnCon;
private JButton btnExit;
private JButton btnSend;
// private static String HOST="192.168.31.168";
private static String HOST = "127.0.0.1";// Own machine , Server's ip Address
private static int PORT = 9090;// Port number of the server
private Socket clientSocket;
private PrintWriter pw;
public ClientForm() {
super(" Instant messaging tools 1.0");
// Menu bar
addJMenu();
// The upper panel
JPanel p = new JPanel();
JLabel jlb1 = new JLabel(" User ID :");
tfdUserName = new JTextField(10);
// tfdUserName.setEnabled(false);// Cannot select and modify
// dtfdUserName.setEditable(false);// Do not modify
// Link button
ImageIcon icon = new ImageIcon("a.png");
btnCon = new JButton("", icon);
btnCon.setActionCommand("c");
btnCon.addActionListener(this);
// Exit button
icon = new ImageIcon("b.jpg");
btnExit = new JButton("", icon);
btnExit.setActionCommand("exit");
btnExit.addActionListener(this);
btnExit.setEnabled(false);
p.add(jlb1);
p.add(tfdUserName);
p.add(btnCon);
p.add(btnExit);
getContentPane().add(p, BorderLayout.NORTH);
// The middle panel
JPanel cenP = new JPanel(new BorderLayout());
this.getContentPane().add(cenP, BorderLayout.CENTER);
// Online list
lm = new DefaultListModel<String>();
list = new JList<String>(lm);
lm.addElement(" All ");
list.setSelectedIndex(0);// Set the default display
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);// Only one row can be selected
list.setVisibleRowCount(2);
JScrollPane js = new JScrollPane(list);
Border border = new TitledBorder(" On-line ");
js.setBorder(border);
Dimension preferredSize = new Dimension(70, cenP.getHeight());
js.setPreferredSize(preferredSize);
cenP.add(js, BorderLayout.EAST);
// Chat message box
allMsg = new JTextArea();
allMsg.setEditable(false);
cenP.add(new JScrollPane(allMsg), BorderLayout.CENTER);
// Message sending panel
JPanel p3 = new JPanel();
JLabel jlb2 = new JLabel(" news :");
p3.add(jlb2);
tfdMsg = new JTextField(20);
p3.add(tfdMsg);
btnSend = new JButton(" send out ");
btnSend.setEnabled(false);
btnSend.setActionCommand("send");
btnSend.addActionListener(this);
p3.add(btnSend);
this.getContentPane().add(p3, BorderLayout.SOUTH);
// *************************************************
// In the top right corner of the X- close button - Add event handling
addWindowListener(new WindowAdapter() {
// Adapter
@Override
public void windowClosing(WindowEvent e) {
if (pw == null) {
System.exit(0);
}
String msg = "[email protected]#@# All @#@#[email protected]#@#" + tfdUserName.getText();
pw.println(msg);
pw.flush();
System.exit(0);
}
});
setBounds(300, 300, 400, 300);
setVisible(true);
}
private void addJMenu() {
JMenuBar menuBar = new JMenuBar();
this.setJMenuBar(menuBar);
JMenu menu = new JMenu(" Options ");
menuBar.add(menu);
JMenuItem menuItemSet = new JMenuItem(" Set up ");
JMenuItem menuItemHelp = new JMenuItem(" help ");
menu.add(menuItemSet);
menu.add(menuItemHelp);
menuItemSet.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final JDialog dlg = new JDialog(ClientForm.this);// An interface pops up
// Can't be used directly this
dlg.setBounds(ClientForm.this.getX()+20, ClientForm.this.getY()+30,
350, 150);
dlg.setLayout(new FlowLayout());
dlg.add(new JLabel(" The server IP And port :"));
final JTextField tfdHost = new JTextField(10);
tfdHost.setText(ClientForm.HOST);
dlg.add(tfdHost);
dlg.add(new JLabel(":"));
final JTextField tfdPort = new JTextField(5);
tfdPort.setText(""+ClientForm.PORT);
dlg.add(tfdPort);
JButton btnSet = new JButton(" Set up ");
dlg.add(btnSet);
btnSet.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String ip = tfdHost.getText();// Analyze and judge ip Is it legal
String strs[] = ip.split("\\.");
if(strs==null||strs.length!=4){
JOptionPane.showMessageDialog(ClientForm.this, "IP Wrong type !");
return ;
}
try {
for(int i=0;i<4;i++){
int num = Integer.parseInt(strs[i]);
if(num>255||num<0){
JOptionPane.showMessageDialog(ClientForm.this, "IP Wrong type !");
return ;
}
}
} catch (NumberFormatException e2) {
JOptionPane.showMessageDialog(ClientForm.this, "IP Wrong type !");
return ;
}
ClientForm.HOST=tfdHost.getText();// First analyze and judge ip Is it legal
try {
int port = Integer.parseInt( tfdPort.getText() );
if(port<0||port>65535){
JOptionPane.showMessageDialog(ClientForm.this, " Wrong port range !");
return ;
}
} catch (NumberFormatException e1) {
JOptionPane.showMessageDialog(ClientForm.this, " Wrong port type !");
return ;
}
ClientForm.PORT=Integer.parseInt( tfdPort.getText() );
dlg.dispose();// Close this interface
}
});
dlg.setVisible(true);// Show it
}
});
menuItemHelp.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JDialog dlg = new JDialog(ClientForm.this);
dlg.setBounds(ClientForm.this.getX()+30,ClientForm.this.getY()+30, 400, 100);
dlg.setLayout(new FlowLayout());
dlg.add(new JLabel(" Version all @ Chen Haoxiang .2016.5.16 My home page :http://chenhaoxiang.github.io"));
dlg.setVisible(true);
}
});
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("c")) {
if (tfdUserName.getText() == null
|| tfdUserName.getText().trim().length() == 0
|| "@#@#".equals(tfdUserName.getText())
|| "@#".equals(tfdUserName.getText())) {
JOptionPane.showMessageDialog(this, " User name input error , Please re-enter !");
return;
}
connecting();// Action to connect to the server
if (pw == null) {
JOptionPane.showMessageDialog(this, " The server is not turned on or the network is not connected , Unable to connect !");
return;
}
((JButton) (e.getSource())).setEnabled(false);
// get btnCon Button -- Get the source
// amount to btnCon.setEnabled(false);
btnExit.setEnabled(true);
btnSend.setEnabled(true);
tfdUserName.setEditable(false);
} else if (e.getActionCommand().equals("send")) {
if (tfdMsg.getText() == null
|| tfdMsg.getText().trim().length() == 0) {
return;
}
String msg = "[email protected]#@#" + list.getSelectedValue() + "@#@#"
+ tfdMsg.getText() + "@#@#" + tfdUserName.getText();
pw.println(msg);
pw.flush();
// Set the text of the sent message to null
tfdMsg.setText("");
} else if (e.getActionCommand().equals("exit")) {
// First clear your online menu
lm.removeAllElements();
sendExitMsg();
btnCon.setEnabled(true);
btnExit.setEnabled(false);
tfdUserName.setEditable(true);
}
}
// Send an exit message to the server
private void sendExitMsg() {
String msg = "[email protected]#@# All @#@#[email protected]#@#" + tfdUserName.getText();
System.out.println(" sign out :" + msg);
pw.println(msg);
pw.flush();
}
private void connecting() {
try {
// Take precautions according to the user name first
String userName = tfdUserName.getText();
if (userName == null || userName.trim().length() == 0) {
JOptionPane.showMessageDialog(this, " Failed to connect to server !\r\n Wrong user name , Please re-enter !");
return;
}
clientSocket = new Socket(HOST, PORT);// Shake hands with the server
pw = new PrintWriter(clientSocket.getOutputStream(), true);// Plus auto refresh
pw.println(userName);// Report your user name to the server
this.setTitle(" user [ " + userName + " ] go online ...");
new ClientThread().start();// Accept messages from the server --- Always on
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
class ClientThread extends Thread {
@Override
public void run() {
try {
Scanner sc = new Scanner(clientSocket.getInputStream());
while (sc.hasNextLine()) {
String str = sc.nextLine();
String msgs[] = str.split("@#@#");
System.out.println(tfdUserName.getText() + ": " + str);
if ("msg".equals(msgs[0])) {
if ("server".equals(msgs[1])) {// The official message sent by the server
str = "[ notice ]:" + msgs[2];
} else {// Chat messages forwarded by the server
str = "[ " + msgs[1] + " ] say : " + msgs[2];
}
allMsg.append("\r\n" + str);
}
if ("cmdAdd".equals(msgs[0])) {
boolean eq = false;
for (int i = 0; i < lm.getSize(); i++) {
if (lm.getElementAt(i).equals(msgs[2])) {
eq = true;
}
}
if (!eq) {
lm.addElement(msgs[2]);// Users go online -- add to
}
}
if ("cmdRed".equals(msgs[0])) {
lm.removeElement(msgs[2]);// The user is offline -- remove
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
JFrame.setDefaultLookAndFeelDecorated(true);// Set decoration
new ClientForm();
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
- 248.
- 249.
- 250.
- 251.
- 252.
- 253.
- 254.
- 255.
- 256.
- 257.
- 258.
- 259.
- 260.
- 261.
- 262.
- 263.
- 264.
- 265.
- 266.
- 267.
- 268.
- 269.
- 270.
- 271.
- 272.
- 273.
- 274.
- 275.
- 276.
- 277.
- 278.
- 279.
- 280.
- 281.
- 282.
- 283.
- 284.
- 285.
- 286.
- 287.
- 288.
- 289.
- 290.
- 291.
- 292.
- 293.
- 294.
- 295.
- 296.
- 297.
- 298.
- 299.
- 300.
- 301.
- 302.
- 303.
- 304.
- 305.
- 306.
- 307.
- 308.
- 309.
- 310.
- 311.
- 312.
- 313.
- 314.
- 315.
- 316.
- 317.
- 318.
- 319.
- 320.
- 321.
- 322.
- 323.
- 324.
- 325.
- 326.
- 327.
- 328.
- 329.
- 330.
- 331.
- 332.
- 333.
- 334.
- 335.
- 336.
- 337.
- 338.
- 339.
- 340.
- 341.
- 342.
- 343.
- 344.
- 345.
- 346.
- 347.
- 348.
- 349.
- 350.
- 351.
- 352.
- 353.
- 354.
- 355.
- 356.
- 357.
- 358.
- 359.
版权声明
本文为[51CTO]所创,转载请带上原文链接,感谢
https://cdmana.com/2022/134/202205141204236675.html