网络编程-第二节

Posted wei01

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络编程-第二节相关的知识,希望对你有一定的参考价值。

技术分享图片

1.1  基础题:客户端与服务器持续通信

1.2      应用题:设计带窗口客户端

导入程序MyServer.java、MyClient.java、ClientThread.java。补充程序MyClient.java的代码(在“//TODO 添加代码”提示的位置),使得

1)       客户端在运行之后打开如下窗口,用户可以从文本框”Message:”中输入信息,点击“Send”之后,将信息发送给服务器,并将其显示在文本区域中;

2)       客户端接收到服务器回复的信息,将其显示在文本区域”Information Border”中;

MyServer.java代码如下:

package cn.edu.sise;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import javax.swing.JOptionPane;

/**
 * Echo服务器:根据Echo协议,接收来自客户机消息,并立即回送。
 * @author 董相志,版权所有,2016--2018,[email protected]
 */
public class MyServer extends javax.swing.JFrame {
    private ServerSocket listenSocket=null; //侦听套接字
    private Socket toClientSocket=null; //与客户机对话的套接字
    public static int clientCounts=0; //客户数量编号
    /**
     * Creates new form EchoServer
     */
    public MyServer() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        topPanel = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        txtHostName = new javax.swing.JTextField();
        jLabel2 = new javax.swing.JLabel();
        txtHostPort = new javax.swing.JTextField();
        btnStart = new javax.swing.JButton();
        midPanel = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        txtArea = new javax.swing.JTextArea();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("My Server: 1707");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        topPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Server Info Border", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("宋体", 1, 18))); // NOI18N

        jLabel1.setFont(new java.awt.Font("宋体", 1, 16)); // NOI18N
        jLabel1.setText("Host Name:");

        txtHostName.setFont(new java.awt.Font("宋体", 1, 16)); // NOI18N
        txtHostName.setText("localhost");

        jLabel2.setFont(new java.awt.Font("宋体", 1, 16)); // NOI18N
        jLabel2.setText("Port:");

        txtHostPort.setFont(new java.awt.Font("宋体", 1, 16)); // NOI18N
        txtHostPort.setText("7");

        btnStart.setFont(new java.awt.Font("宋体", 1, 16)); // NOI18N
        btnStart.setText("Start");
        btnStart.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnStartActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout topPanelLayout = new javax.swing.GroupLayout(topPanel);
        topPanel.setLayout(topPanelLayout);
        topPanelLayout.setHorizontalGroup(
            topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(topPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(txtHostName, javax.swing.GroupLayout.DEFAULT_SIZE, 131, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jLabel2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(txtHostPort, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(btnStart)
                .addContainerGap())
        );
        topPanelLayout.setVerticalGroup(
            topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(topPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(txtHostName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel2)
                    .addComponent(txtHostPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(btnStart))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        getContentPane().add(topPanel, java.awt.BorderLayout.PAGE_START);

        midPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Information Border", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("宋体", 1, 18))); // NOI18N
        midPanel.setLayout(new java.awt.BorderLayout());

        txtArea.setEditable(false);
        txtArea.setBackground(new java.awt.Color(204, 255, 255));
        txtArea.setColumns(20);
        txtArea.setFont(new java.awt.Font("宋体", 1, 16)); // NOI18N
        txtArea.setRows(5);
        jScrollPane1.setViewportView(txtArea);

        midPanel.add(jScrollPane1, java.awt.BorderLayout.CENTER);

        getContentPane().add(midPanel, java.awt.BorderLayout.CENTER);

        pack();
    }// </editor-fold>//GEN-END:initComponents
    //启动服务器
    private void btnStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStartActionPerformed
    
        try {
            btnStart.setEnabled(false); //禁用按钮,避免重复启动
            String hostName=txtHostName.getText();//主机名
            int hostPort=Integer.parseInt(txtHostPort.getText());//端口
            //构建服务器的SocketAddress格式地址
            SocketAddress serverAddr=new InetSocketAddress(InetAddress.getByName(hostName),hostPort);
            listenSocket=new ServerSocket(); //创建侦听套接字
            listenSocket.bind(serverAddr);  //绑定到工作地址 
            txtArea.append("服务器开始等待客户机连接...
");             
        } catch (IOException ex) {    }
        
        //创建一个匿名线程,用于侦听和接受客户机连接,并创建响应客户机的会话线程
        new Thread(new Runnable() {  
            @Override
            public void run() {
                try {
                    while (true) { //处理客户机连接
                        toClientSocket=listenSocket.accept();//侦听并接受客户机连接
                        clientCounts++;//客户机数量加1
                        txtArea.append(toClientSocket.getRemoteSocketAddress()+ " 客户机编号: "+clientCounts+ " 会话开始...
");
                        //创建客户线程clientThread,实现一客户一线程
                       Thread clientThread=new ClientThread(toClientSocket,clientCounts); 
                        clientThread.start(); //启动任务线程
                    } //end while                                     
                } catch (IOException ex) {
                    JOptionPane.showMessageDialog(null, ex.getMessage(), "错误提示", JOptionPane.ERROR_MESSAGE);
                }           
            }//end run()
        }).start();
    }//GEN-LAST:event_btnStartActionPerformed
    //关闭服务器之前
    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        //关闭服务器之前释放套接字
        if (listenSocket!=null) listenSocket=null;
        if (toClientSocket!=null) toClientSocket=null;
    }//GEN-LAST:event_formWindowClosing

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(MyServer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(MyServer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(MyServer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MyServer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>
        //</editor-fold>
        //</editor-fold>
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MyServer().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnStart;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JPanel midPanel;
    private javax.swing.JPanel topPanel;
    public static javax.swing.JTextArea txtArea;
    private javax.swing.JTextField txtHostName;
    private javax.swing.JTextField txtHostPort;
    // End of variables declaration//GEN-END:variables
}

MyClient.java代码如下:

package cn.edu.sise;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class MyClient {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        // TODO 1.添加代码:在窗口标题里写上自己的学号
        JFrame frame = new JFrame("Client: 1707");

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.getContentPane().add(new MyPanel());
        frame.setPreferredSize(new Dimension(600, 300));
        frame.pack();
        frame.setVisible(true);
    }

}

class MyPanel extends JPanel {
    JTextField tf;
    JTextArea ta;

    BufferedReader in = null;
    BufferedWriter out = null;

    public MyPanel() {

        this.setLayout(new BorderLayout());
        JPanel p1 = new JPanel();
        JLabel lb1 = new JLabel();
        lb1.setFont(new java.awt.Font("宋体", 1, 16)); // NOI18N
        lb1.setText("Message:");
        p1.add(lb1);
        tf = new JTextField(25);
        p1.add(tf);
        JButton btn = new JButton("Send");
        btn.addActionListener(new MyListerner());
        p1.add(btn);
        p1.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Communication Border",
                javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION,
                new java.awt.Font("宋体", 1, 14))); // NOI18N

        this.add(p1, BorderLayout.NORTH);

        JPanel p2 = new JPanel();
        p2.setLayout(new java.awt.BorderLayout());
        p2.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Information Border",
                javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION,
                new java.awt.Font("宋体", 1, 14))); // NOI18N

        JScrollPane sp1 = new JScrollPane();
        sp1.setPreferredSize(new java.awt.Dimension(8, 250));
        ta = new JTextArea(5, 10);
        ta.setEditable(false);
        sp1.setViewportView(ta);
        p2.add(sp1, BorderLayout.CENTER);
        this.add(p2, BorderLayout.CENTER);

        try {
            Socket s = new Socket();
            // TODO 2.添加代码 1) 新建SocketAddress的对象,指定要连接的服务器;
            // 2)调用Socket的方法连接服务器

            SocketAddress address=new InetSocketAddress("localhost",7);

            // 连接服务器
            s.connect(address);
            

            in = new BufferedReader(new InputStreamReader(s.getInputStream()));
            // TODO 3.添加代码 : 上面已给出输入流的代码,请补充输出流的
            out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

        } catch (IOException ex) {
            System.out.println("异常信息:" + ex.getMessage());
        }
    }

    class MyListerner implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub

            String sendStr = tf.getText(); // 从文本框中读取用户输入
            tf.setText("");// 将文本框中的字符清空
            // TODO 4.添加代码:向服务器发送字符串
            try{
                out.write(sendStr);
                out.newLine();
                out.flush();
            }catch (IOException ex) {
                System.out.println("异常信息:"+ex.getMessage());
            
            }    
            

            System.out.println("向服务器发送字符串成功!" + sendStr);

            ta.append("To server: " + sendStr + "
");// 将字符串显示在文本区域

            // TODO 5.添加代码: 接收服务器回复的字符串,并显示在文本区域
            try{
            ta.append("Recv: " + in.readLine() + ‘
‘);
            }catch (IOException ex) {
                System.out.println("异常信息:"+ex.getMessage());
            
            }

        }
    }
}

ClientThread.java代码如下:

package cn.edu.sise;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 *
 * @author World
 */
public class ClientThread extends Thread {
    private Socket toClientSocket=null;//会话套接字
    private BufferedReader in; //网络输入流
    private PrintWriter out; //网络输出流
    private int clientCounts=0;//在线客户机总数
    public ClientThread(Socket toClientSocket,int clientCounts) { //构造函数
        this.toClientSocket=toClientSocket;
        this.clientCounts=clientCounts;
    }    
    @Override
    public void run(){
        try {          
            // 创建绑定到套接字toClientSocket上的网络输入流与输出流
            in=new BufferedReader(new InputStreamReader(toClientSocket.getInputStream(),"UTF-8"));
            out=new PrintWriter(new OutputStreamWriter(toClientSocket.getOutputStream(),"UTF-8"),true);
            //5. 根据服务器协议,在网络流上进行读写操作
            String recvStr;
            while ((recvStr=in.readLine())!=null){ //只要客户机不关闭,则反复等待和接收客户机消息
               Date date=new Date();
               DateFormat format=new SimpleDateFormat("yyyy-mm-dd hh:mm:ss");
               String time=format.format(date);
               MyServer.txtArea.append(toClientSocket.getRemoteSocketAddress()+ " 客户机编号: "+clientCounts+" 消息:"+recvStr+" :"+time+"
"); //解析并显示收到的消息
               //按照echo协议原封不动回送消息
               out.println(toClientSocket.getLocalSocketAddress()+ " 客户机编号: "+clientCounts+" Echo消息:"+recvStr+" : "+time);
            }//end while   
            MyServer.clientCounts--; //客户机总数减1
            //远程客户机断开连接,线程释放资源
            if (in!=null) in.close();
            if (out!=null) out.close();
            if (toClientSocket!=null) toClientSocket.close();             
        }catch (IOException ex) {}
    } //end run
} //end class

运行结果:

技术分享图片

 

以上是关于网络编程-第二节的主要内容,如果未能解决你的问题,请参考以下文章

软件构造第二章第二节 软件构造的过程系统和工具

网络第二节——AFNworking

cisco网络基础小实验第二节

第二节 获取词向量的工具——Word2Vec

网络知识梳理(第二节)

《Linux内核分析》 第二节 操作系统是如何工作的