分享一波新浪java面试题与参考答案解析

点关注,不迷路;持续更新Java相关技术及资讯!!!

在这里插入图片描述

本文主要介绍了新浪java面试题与参考答案,总结分析了新浪java面试网络编程题目与参考答案,涉及java socket通信客户端与服务器端功能实现技巧,需要的朋友可以参考下

在服务器端 用一个HashMap<userName,socket> 维护所有用户相关的信息,从而能够保证和所有的用户进行通讯。

客户端的动作:
(1)连接(登录):发送userName 服务器的对应动作:1)界面显示,2)通知其他用户关于你登录的信息, 3)把其他在线用户的userName通知当前用户 4)开启一个线程专门为当前线程服务
(2)退出(注销):
(3)发送消息

※※发送通讯内容之后,对方如何知道是干什么,通过消息协议来实现:

客户端向服务器发的消息格式设计:
命令关键字@#接收方@#消息内容@#发送方

1)连接:userName ----握手的线程serverSocket专门接收该消息,其它的由服务器新开的与客户进行通讯的socket来接收

2)退出:exit@#全部@#null@#userName

3)发送: on @# JList.getSelectedValue() @# tfdMsg.getText() @# tfdUserName.getText()
服务器向客户端发的消息格式设计:
命令关键字@#发送方@#消息内容

登录:

  1. msg @#server @# 用户[userName]登录了 (给客户端显示用的)
  2. cmdAdd@#server @# userName (给客户端维护在线用户列表用的)
    退出:
  3. msg @#server @# 用户[userName]退出了 (给客户端显示用的)
  4. cmdRed@#server @# userName (给客户端维护在线用户列表用的)
    发送:
    msg @#消息发送者( msgs[3] ) @# 消息内容 (msgs[2])
    运行结果如下:
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.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.border.TitledBorder;
public class ServerForm extends JFrame{
    private DefaultListModel lm;
    private JTextArea area;
    private final static int PORT=10010;
    private Map<String, Socket> map=new HashMap<String, Socket>();
        public ServerForm() {
                setDefaultCloseOperation(EXIT_ON_CLOSE);
                //setBounds(x, y, width, height)
                final int winWidth=(int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
                final int winHeight=(int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
                setBounds(winWidth/4, winHeight/4, winWidth/2, winHeight/2);
                //加聊天面板
                area=new JTextArea();
                area.setEditable(false);
                this.getContentPane().add(new JScrollPane(area),BorderLayout.CENTER);
                lm=new DefaultListModel();
                JList list=new JList(lm);
                JScrollPane js=new JScrollPane(list);
                js.setBorder(new TitledBorder("在线"));
                js.setPreferredSize(new Dimension(180, this.getHeight()));
                getContentPane().add(js,BorderLayout.EAST);
                JMenuBar bar=new JMenuBar();
                JMenu menu=new JMenu("控制");
                menu.setMnemonic('C');//助记符
                final JMenuItem run=new JMenuItem("开启");
                run.setAccelerator(KeyStroke.getKeyStroke('R',KeyEvent.CTRL_MASK));//设置快捷键ctrl+R
                run.setActionCommand("run");
                menu.add(run);
                menu.addSeparator();
                JMenuItem exit=new JMenuItem("退出");
                exit.setAccelerator(KeyStroke.getKeyStroke('E',KeyEvent.CTRL_MASK));
                exit.setActionCommand("exit");
                menu.add(exit);
                bar.add(menu);
                setJMenuBar(bar);
                //监听
                ActionListener action=new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                if(e.getActionCommand().equals("run")){
                        startServer();
                        run.setEnabled(false);
                }else{
                        System.exit(0);
                }
                        }
                };
                run.addActionListener(action);
                exit.addActionListener(action);
                setVisible(true);
        }
        public static void main(String[] args) {
        JFrame.setDefaultLookAndFeelDecorated(true);
        new ServerForm();
        }
        private void startServer() {
                try {
                        ServerSocket server=new ServerSocket(PORT);
                        area.setText("启动服务"+server);
                        new ServerThread(server).start();
                } catch (IOException e) {
                        e.printStackTrace();
                }
        }
        class ServerThread extends Thread{
        private ServerSocket server;
                public ServerThread(ServerSocket server) {
                        this.server = server;
                }
                @Override
                public void run() {
                        while(true){
                                //握手,第一次。专门来接待客户端第一次链接。
                                try {
                                        Socket socketClient=server.accept();
                                        Scanner sc=new Scanner(socketClient.getInputStream());
                                        if(sc.hasNext()){
                                                //System.out.println("..........");
                                                String userName=sc.nextLine();
                                                area.append("\r\n用户"+userName+"登录"+socketClient);
                                                lm.addElement(userName);
                                                new ClientThread(socketClient).start();
                                                msgAll(userName);//把当前用户登陆的消息通知给所有在线的人。
                                                msgSelf(socketClient);//通知自己当前在线的所有人。
                                                //把当前登陆的用户加到在线用户列表中
                                                map.put(userName,socketClient);
                                        }
                                } 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("一个与客户端通讯的线程启动");
                                try {
                                        Scanner sc=new Scanner(socketClient.getInputStream());
                                        while(sc.hasNext()){
                                                String msg=sc.nextLine();
                                                String msgs[]=msg.split("@#");
                                                //防黑
                                                if(msgs.length!=4){
                                                        System.out.println("防黑处理");
                                                }
                                                if("on".equals(msgs[0])){
                                                        sendMsgToSb(msgs);
                                                }
                                                if("exit".equals(msgs[0])){
                                                        //从在线用户map中把该用户删掉
                                                        map.remove(msgs[3]);
                                                        //从服务器的在线列表中把该用户删除
                                                        lm.removeElement(msgs[3]);
                                                        //通知其他在线用户有关退出的消息
                                                        sendExitMsgToAll(msgs);
                                                        //在服务器窗口显示该用户退出的消息
                                                        area.append("\r\n用户"+msgs[3]+"退出了");
                                                }
                                        }
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                }
        }
        //服务器把客户端的聊天消息转发给相应的其它客户端
        private void sendMsgToSb(String[] msgs) throws Exception {
                if("全部".equals(msgs[1])){
                        Iterator it=map.keySet().iterator();
                        while(it.hasNext()){//遍历每一个在线用户,把聊天消息转发给他
                                String userName=(String) it.next();
                                Socket s=map.get(userName);
                                PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
                                String str="msg@#"+msgs[3]+"@#"+msgs[2];
                                pw.println(str);
                                pw.flush();
                        }
                }else{
                        Socket s=map.get(msgs[1]);
                        PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
                        String str="msg@#"+msgs[3]+"@#"+msgs[2];
                        pw.println(str);
                        pw.flush();
                }
        }
        //通知其他在线用户有人退出了
        private void sendExitMsgToAll(String[] msgs) throws IOException {
        Iterator<String> it=map.keySet().iterator();
        while(it.hasNext()){
                String userName=it.next();
                Socket s=map.get(userName);
                PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
                String str="msg@#server@#用户["+msgs[3]+"]退出了";
                pw.println(str);
                pw.flush();
                str="cmdRed@#server@#"+msgs[3];
                pw.println(str);
                pw.flush();
        }
        }
        private void msgAll(String userName) {
                 Iterator<Socket> it=map.values().iterator();
                 while(it.hasNext()){
                         Socket s=it.next();
                         PrintWriter pw;
                        try {//把服务器要我们做的事情变成协议格式,由我们来解析
                                pw = new PrintWriter(s.getOutputStream(),true);
                                String msg="msg@#server@#用户["+userName+"]登陆了";
                                pw.println(msg);
                                //pw.flush();
                                msg="cmdAdd@#server@#"+userName;
                                pw.println(msg);
                                //pw.flush();
                        } catch (IOException e) {
                                e.printStackTrace();
                        }
                 }
        }
        private void msgSelf(Socket socketClient) {
                try {
                        PrintWriter pw=new PrintWriter(socketClient.getOutputStream(),true);
                        Iterator it=map.keySet().iterator();
                        while(it.hasNext()){
                                pw.println("cmdAdd@#server@#"+it.next());
                                //pw.flush();
                        }
                } catch (IOException e) {
                        e.printStackTrace();
                }
        }
}


客户端

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.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.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.border.TitledBorder;
public class ClientForm  extends JFrame implements ActionListener{
        private JButton btnConn;
        private JButton btnExit;
        private DefaultListModel lm;
        private JTextArea allMsg;
        private JTextField text;
        private JTextField userText;
        private JList list;
        private  static String HOST="127.0.0.1";
        private  static int PORT=10010;
        public ClientForm() {
                //菜单条
                addMenu();
                setBounds(300, 200, 500, 400);
                //上部面板
                JPanel panel=new JPanel();
                panel.add(new JLabel("用户标识"));
                panel.add(this.userText=new JTextField(10));
                panel.add(this.btnConn=new JButton("连接"));
                btnConn.addActionListener(this);
                btnConn.setActionCommand("conn");
                //btnConn.addActionListener(this);
                panel.add(this.btnExit=new JButton("退出"));
                btnExit.addActionListener(this);
                btnExit.setActionCommand("exit");
                this.getContentPane().add(panel,BorderLayout.NORTH);
                //中部面板
                //lm=new ListModel() ;
                //JList list=new JList(dataModel)
                JPanel panelC=new JPanel(new BorderLayout());//默认是FlowLayout
                this.getContentPane().add(panelC,BorderLayout.CENTER);
                lm=new DefaultListModel();
                list=new JList(lm);
            lm.addElement("全部");
            list.setSelectedIndex(0);
            list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            list.setVisibleRowCount(2);
            JScrollPane js=new JScrollPane(list);
            js.setBorder(new TitledBorder("在线"));
            //注意,在使用布局方式控制组件时,最好使用setPreferredSize来控制大小,使用setSize有时会失效。
            js.setPreferredSize(new Dimension(150, panelC.getHeight()));
            //js.setSize(150, panelC.getHeight());
            panelC.add(js,BorderLayout.EAST);
            allMsg=new JTextArea();
            allMsg.setEditable(false);
            panelC.add(new JScrollPane(allMsg),BorderLayout.CENTER);
            //消息发送面板
            JPanel panelS=new JPanel();
            panelS.add(new JLabel("消息"));
            text=new JTextField(20);
            panelS.add(text);
                JButton btnSend=new JButton("发送");
                panelS.add(btnSend);
                btnSend.addActionListener(this);
                btnSend.setActionCommand("send");
                panelC.add(panelS,BorderLayout.SOUTH);
                //给窗口右上角的关闭按钮添加事件处理
                addWindowListener(new WindowAdapter() {
                        @Override
                        public void windowClosing(WindowEvent e) {
                                sendExitMsg();
                        }
                });
                setVisible(true);
        }
        private void addMenu() {
        JMenuBar menuBar=new JMenuBar();
        JMenu menu=new JMenu("选项");
        JMenuItem item=new JMenuItem("设置");
        JMenuItem help=new JMenuItem("帮助");
        setJMenuBar(menuBar);
        menuBar.add(menu);
        menu.add(item);
        menu.add(help);
        help.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                JDialog dlg=new JDialog(ClientForm.this);
                                dlg.setBounds(ClientForm.this.getX(), ClientForm.this.getY(),300, 100);
                                dlg.setLayout(new FlowLayout());
                                dlg.add(new JLabel("版本所有@城院杜雅倩qq:1115179167"));
                                dlg.setVisible(true);
                        }
                });
        item.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                final JDialog dlg=new JDialog(ClientForm.this);
                                dlg.setBounds(ClientForm.this.getX(), ClientForm.this.getY(),300, 100);
                                dlg.setLayout(new FlowLayout());
                                dlg.add(new JLabel("服务器"));
                                final JTextField host=new JTextField(10);
                                host.setText(HOST);
                                dlg.add(host);
                                dlg.add(new JLabel(":"));
                                final JTextField port=new JTextField(5);
                                port.setText(""+PORT);
                                dlg.add(port);
                                JButton btnSet=new JButton("设置");
                                dlg.add(btnSet);
                                btnSet.addActionListener(new ActionListener() {
                                        @Override
                                        public void actionPerformed(ActionEvent e) {
                                                //按理应该先解析并判断端口号是否合法,此处省略了
                        HOST=host.getText();
                        //System.out.println(HOST);
                        PORT=Integer.parseInt(port.getText());
                        //System.out.println(PORT);
                        dlg.dispose();//关闭并销毁该对话框,清理内存
                                        }
                                });
                                dlg.setVisible(true);
                        }
                });
        }
        public static void main(String[] args) {
                JFrame.setDefaultLookAndFeelDecorated(true);
        new ClientForm();
        }
        @Override
        public void actionPerformed(ActionEvent e) {
                if(e.getActionCommand().equals("conn")){
                        System.out.println("连接服务器。。。");
                        try {
                                connecting();
                                ((JButton)e.getSource()).setEnabled(false);
                                //setEnabled(false);
                                userText.setEditable(false);
                        } catch (IOException e1) {
                                JOptionPane.showMessageDialog(this, "服务器连接失败,请检查网络或者查看服务器地址与端口号");
                        }
                }
                if(e.getActionCommand().equals("send")){
                        if(text.getText()==null || text.getText().trim().length()==0){
                                JOptionPane.showMessageDialog(this, "请输入聊天消息");
                                return;
                        }
                        String msg="on@#"+list.getSelectedValue()+"@#"+text.getText()+"@#"+userText.getText();
                        pw.println(msg);
                }
                if(e.getActionCommand().endsWith("exit")){
                        sendExitMsg();
                        //((JButton)e.getSource()).setEnabled(false);
                        System.exit(0);
                }
        }
        //向服务器发送退出消息
        private void sendExitMsg() {
                 if(client==null){
                         System.exit(0);
                 }
                 String msg="exit@#全部@#null@#"+userText.getText();
                 System.out.println("退出"+msg);
                 pw.println(msg);
                 pw.flush();
                 System.exit(0);
        }
        private Socket client;
        private PrintWriter pw;
        private void connecting() throws IOException {
                        client=new Socket(HOST, PORT);
                        String userName=userText.getText();
                        pw=new PrintWriter(client.getOutputStream(),true);
                        pw.println(userName);
                        this.setTitle("用户"+"["+userName+"]"+"在线");
                        //服务器也要给我们发消息的,比如说谁在线等消息。这里是在图形界面线程,最好另外开一个线程来相应。
                        new ClientThread().start();
        }
    class ClientThread extends Thread{
                @Override
                public void run() {
                        //用来接收服务器给我们发送的消息
                        try {
                                Scanner sc = new Scanner(client.getInputStream());
                                while(sc.hasNext()){
                                        String str=sc.nextLine();
                                        //拆分服务器发送过来的消息,并解析
                                        String[] msgs=str.split("@#");
                                        if("msg".equals(msgs[0])){
                                                if("server".equals(msgs[1])){
                                                        str="[通知]:"+msgs[2];
                                                }else {//服务器转发的聊天消息
                                                        str=msgs[1]+"说"+msgs[2];
                                                }
                                                allMsg.append("\r\n"+str);//在用户聊天面板里添加消息
                                        }else if("cmdAdd".equals(msgs[0])){
                                                lm.addElement(msgs[2]);        //实时维护用户在线列表
                                        }else{
                                                lm.removeElement(msgs[2]);
                                        }
                                }
                        } catch (IOException e) {
                                e.printStackTrace();
                        }
                }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41770757/article/details/106447075