zoukankan      html  css  js  c++  java
  • Java网络编程技术2

    3. UDP数据报通信

    UDP通信中,需要建立一个DatagramSocket,与Socket不同,它不存在“连接”的概念,取而代之的是一个数据报包——DatagramPacket。这个数据报包必须知道自己来自何处,以及打算去哪里。所以本身必须包含IP地址、端口号和数据内容。

    3.1 示例程序——用UDP实现的聊天程序

    用UDP协议通信不需要使用服务器,所以用于聊天的程序只要写一个,分别在不同的机器上运行就可以了,而无须写成服务端和客户端两种形式。

    例9. 用UDP实现的聊天程序示例。

    package Net.UDPchat;
    import java.awt.BorderLayout;
    import java.awt.Container;
    import java.awt.FlowLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.IOException;
    import java.net.*;
    
    import javax.swing.*;
    public class UDPchat implements ActionListener,Runnable {
        JFrame jf;
        JLabel jl1,jl2,jl3;
        JTextField recPortText,sendPortText,IPText,msgText;
        JButton startBtn,sendBtn;
        JTextArea showArea;
        JScrollPane jsp;
        JPanel jp1,jp2;
        Container con;
        Thread thread = null;
        DatagramSocket receiveSocket,sendSocket;
        DatagramPacket receivePack,sendPack;
        private InetAddress sendIP;
        private int sendPort,recPort;
        private byte inBuf[],outBuf[];
        private static final int BUFSIZE = 1024;
        
        public UDPchat(){
            jf = new JFrame("聊天————UDP协议");
            jl1 = new JLabel("接收端口号:");
            jl2 = new JLabel("发送端口号:");
            jl3 = new JLabel("对方的地址:");
            recPortText = new JTextField();
            recPortText.setColumns(5);
            sendPortText = new JTextField();
            sendPortText.setColumns(5);
            IPText = new JTextField();
            IPText.setColumns(8);
            msgText = new JTextField();
            msgText.setColumns(40);
            msgText.setEditable(false);
            msgText.addActionListener(this);
            startBtn = new JButton("开始");
            startBtn.addActionListener(this);
            sendBtn = new JButton("发送");
            sendBtn.setEnabled(false);
            sendBtn.addActionListener(this);
            showArea = new JTextArea();
            showArea.setEditable(false);
            showArea.setLineWrap(true); //自动换行
            jsp = new JScrollPane(showArea);
            jp1 = new JPanel();
            jp2 = new JPanel();
            jp1.setLayout(new FlowLayout());
            jp2.setLayout(new FlowLayout());
            jp1.add(jl1);
            jp1.add(recPortText);
            jp1.add(jl2);
            jp1.add(sendPortText);
            jp1.add(jl3);
            jp1.add(IPText);
            jp1.add(startBtn);
            jp2.add(msgText);
            jp2.add(sendBtn);
            con = jf.getContentPane();
            con.add(jp1, BorderLayout.NORTH);
            con.add(jsp, BorderLayout.CENTER);
            con.add(jp2, BorderLayout.SOUTH);
            jf.setSize(600, 400);
            jf.setLocation(300, 200);
            jf.setVisible(true);
            jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }
        //在线程中接收数据
        public void run() {
            String str;
            while(true){
                try {
                    receiveSocket.receive(receivePack);
                    str = new String(receivePack.getData(),0,receivePack.getLength());
                    showArea.append("对方说:"+str+"
    ");
                } catch (IOException e) {
                    showArea.append("接收数据出错!
    ");
                }
            }
            
        }
    
        public void actionPerformed(ActionEvent e) {
            try {
                if(e.getSource()==startBtn){
                    inBuf = new byte[BUFSIZE];
                    sendPort = Integer.parseInt(sendPortText.getText());
                    recPort = Integer.parseInt(recPortText.getText());
                    sendIP = InetAddress.getByName(IPText.getText());
                    sendSocket = new DatagramSocket();
                    //创建接收数据包
                    receivePack = new DatagramPacket(inBuf,BUFSIZE);
                    //指定接收数据的端口
                    receiveSocket = new DatagramSocket(recPort);
                    //创建线程准备接收对方的信息
                    thread = new Thread(this);
                    thread.setPriority(Thread.MIN_PRIORITY);
                    thread.start();
                    msgText.setEditable(true);
                    sendBtn.setEnabled(true);
                    startBtn.setEnabled(false);
                }else{ //按下了“发送”按钮或回车键
                    outBuf = msgText.getText().getBytes();
                    //组装要发送的数据
                    sendPack = new DatagramPacket(outBuf,outBuf.length,sendIP,sendPort);
                    //发送数据
                    sendSocket.send(sendPack);
                    showArea.append("我说:"+msgText.getText()+"
    ");
                    msgText.setText(null);
                }
            } catch (NumberFormatException e1) {
                e1.printStackTrace();
            } catch (UnknownHostException e1) {
                showArea.append("无法连接到指定地址
    ");
            } catch (SocketException e1) {
                showArea.append("无法打开指定端口
    ");
            } catch (IOException e1) {
                showArea.append("发送数据失败!
    ");
            }
            
        }
    
        public static void main(String[] args) {
            new UDPchat();
    
        }
    }

    4. Java网络编程的新特性(jdk1.7)

    4.1 轻量级的HTTP服务

    例10. HTTP服务实现的实例。

    package Net.http;
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.io.*;
    import com.sun.net.httpserver.HttpExchange;
    import com.sun.net.httpserver.HttpHandler;
    import com.sun.net.httpserver.HttpServer;
    import com.sun.net.httpserver.spi.HttpServerProvider;
    public class HTTPServer {
        
        public static void main(String[] args) throws Exception {
            //通过HttpServerProvider的静态方法provider,获取HttpServerProvider的对象
            HttpServerProvider httpServerProvider = HttpServerProvider.provider();
            //通过InetSocketAddress类,绑定8080作为服务端口
            InetSocketAddress addr = new InetSocketAddress(8088);
            //调用createHttpServer,创建HTTP服务
            HttpServer httpServer = httpServerProvider.createHttpServer(addr, 1);
            //指定HTTP服务的路径
            httpServer.createContext("/myapp/", new MyHttpHandler());
            httpServer.setExecutor(null);
            //启动服务执行
            httpServer.start();
            //输出服务开始的信息
            System.out.println("started");
        }
    
        static class MyHttpHandler implements HttpHandler {
            //声明抛出异常
            public void handle(HttpExchange httpExchange) throws IOException {
                // 返回客户端的一个字符串
                String response = "This is a simple HTTP Server!";
                // 返回HTTP访问的状态码
                httpExchange.sendResponseHeaders(200, response.length());
                //将返回结果信息输出到客户端
                OutputStream out = httpExchange.getResponseBody();
                out.write(response.getBytes());
                out.close();    
            }
        }
    }

    上述代码是一个可直接运行的Java程序,启动程序运行后,在浏览地址栏中输入访问地址:http://localhost:8088/myapp/,就可以打开页面。

    httpExchange.sendResponseHeaders(int code, int length);其中的code是Http响应的返回值,比如404、403、500等。length指的是response的长度,以字节为单位。

    5. IPv6网络应用程序的开发

    5.1 获取本机IPv6地址

    对地址进行过滤,选出确实可用的地址。下述代码实现了这一功能,思路是遍历网络接口的各个地址,直至找到符合要求的地址。

    例11. 通过Java程序获取本机的IPv6地址。

    package Net.http;
    import java.net.*;
    import java.util.Enumeration;
    import java.io.IOException;
    
    public class GetIPv6Add {
        public static String getLocalIPv6Address() throws IOException{
            InetAddress inetAddress = null;
            //定义一个枚举变量,列出所有的网卡信息
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            outer:
                //遍历所有的网卡,从中找到包含IPv6的地址信息
                while(networkInterfaces.hasMoreElements()){
                    Enumeration<InetAddress> inetAds = networkInterfaces.nextElement().getInetAddresses();
                    while(inetAds.hasMoreElements()){
                        //判断是否是IPv6地址
                        if(inetAddress instanceof Inet6Address && !isReservedAddr(inetAddress)){
                            break outer;
                        }
                    }
                }
            String ipAddr = inetAddress.getHostAddress();
            //过滤掉非地址信息的符号,有些Windows平台上,IP地址的版本信息后面跟着一个%,因而要去掉
            int index = ipAddr.indexOf("%");
            if(index>0){
                ipAddr = ipAddr.substring(0, index);
            }
            return ipAddr;
        }
        /**
         * 过滤本机特殊IP地址
         * @param inetAddr(传入的IP地址作为参数)
         * @return(对传入的IP地址进行判断,返回判断结果
         */
        private static boolean isReservedAddr(InetAddress inetAddr){
            if(inetAddr.isAnyLocalAddress() || inetAddr.isLinkLocalAddress() || inetAddr.isLoopbackAddress()){
                return true;
            }
            return false;
        }
        
        public static void main(String[] args) {
            try {
                System.out.println(getLocalIPv6Address());
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    
    }

    注意:在windows平台上,取得的IPv6地址后面可能跟了一个百分号加数字。这里的数字是本机网络适配器的编号。这个后缀并不是IPv6标准地址的一部分,可以去除。

  • 相关阅读:
    福州KTV
    MSN登陆不上:微软谴责中国的“技术问题”
    DB2 存储过程开发最佳实践
    在DB2存储过程中返回一个数据集
    Host is not allowed to connect to this MySQL server 解决方案
    CentOS安装中文支持
    ImportError: libpq.so.5: cannot open shared object file: No such file or directory
    CentOS 终端显示中文异常解决办法
    pytestDemo
    python 获取当前运行的类名函数名
  • 原文地址:https://www.cnblogs.com/gaopeng527/p/4266121.html
Copyright © 2011-2022 走看看