zoukankan      html  css  js  c++  java
  • udp 双机通信(服务器循环检测)2

    此文摘自:http://blog.csdn.net/qinpeng100423/article/details/8980423,谢谢了

    自己上一篇写的udp通信,只能运行一次,参考了这位博主的,只是把receive的方法处改为循环,这样即可实现服务器循环检测,然后接受数据和回复

    受到项目要求,将文件分离,读者引用该类,实例化调用方法即可。

    一. UDP协议定义

    UDP协议的全称是用户数据报,在网络中它与TCP协议一样用于处理数据包。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据报分组、组装和不能对数据包的排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。

    二. 使用UDP的原因
    它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。比如我们聊天用的ICQ和OICQ就是使用的UDP协议。在选择使用协议的时候,选择UDP必须要谨慎。在网络质量令人不十分满意的环境下,UDP协议数据包丢失会比较严重。

    三. 在Java中使用UDP协议编程的相关类
    1. InetAddress
    用于描述和包装一个Internet IP地址。有如下方法返回实例:
    getLocalhost():返回封装本地地址的实例。

    getAllByName(String host):返回封装Host地址的InetAddress实例数组。

    getByName(String host):返回一个封装Host地址的实例。其中,Host可以是域名或者是一个合法的IP地址。
    InetAddress.getByAddress(addr):根据地址串返回InetAddress实例。
    InetAddress.getByAddress(host, addr):根据主机地符串和地址串返回InetAddress实例。

    2. DatagramSocket
    用于接收和发送UDP的Socket实例。该类有3个构造函数:
    DatagramSocket():通常用于客户端编程,它并没有特定监听的端口,仅仅使用一个临时的。程序会让操作系统分配一个可用的端口。
    DatagramSocket(int port):创建实例,并固定监听Port端口的报文。通常用于服务端

    DatagramSocket(int port, InetAddress localAddr):这是个非常有用的构建器,当一台机器拥有多于一个IP地址的时候,由它创建的实例仅仅接收来自LocalAddr的报文。
    DatagramSocket具有的主要方法如下:
    1)receive(DatagramPacket d):接收数据报文到d中。receive方法产生一个“阻塞”。“阻塞”是一个专业名词,它会产生一个内部循环,使程序暂停在这个地方,直到一个条件触发。

    2)send(DatagramPacket dp):发送报文dp到目的地。

    3)setSoTimeout(int timeout):设置超时时间,单位为毫秒。

    4)close():关闭DatagramSocket。在应用程序退出的时候,通常会主动释放资源,关闭Socket,但是由于异常地退出可能造成资源无法回收。所以,应该在程序完成时,主动使用此方法关闭Socket,或在捕获到异常抛出后关闭Socket。

    3. DatagramPacket
    用于处理报文,它将Byte数组、目标地址、目标端口等数据包装成报文或者将报文拆卸成Byte数组。应用程序在产生数据包是应该注意,TCP/IP规定数据报文大小最多包含65507个,通常主机接收548个字节,但大多数平台能够支持8192字节大小的报文。DatagramPacket类的构建器共有4个:
    DatagramPacket(byte[] buf, int length):将数据包中Length长的数据装进Buf数组,一般用来接收客户端发送的数据。
    DatagramPacket(byte[] buf, int offset, int length):将数据包中从Offset开始、Length长的数据装进Buf数组。
    DatagramPacket(byte[] buf, int length, InetAddress clientAddress, int clientPort):从Buf数组中,取出Length长的数据创建数据包对象,目标是clientAddress地址,clientPort端口,通常用来发送数据给客户端。

    DatagramPacket(byte[] buf, int offset, int length, InetAddress clientAddress, int clientPort):从Buf数组中,取出Offset开始的、Length长的数据创建数据包对象,目标是clientAddress地址,clientPort端口,通常用来发送数据给客户端。
    主要的方法如下:
    1)getData(): 从实例中取得报文的Byte数组编码。
    2)setDate(byte[] buf):将byte数组放入要发送的报文中。


    服务器端:

    新建udpServer.java ,udpServer类代码:

    package com.swust.udp;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.InetSocketAddress;
    import java.net.SocketException;
    
    /**  
     * Copyright 2007 GuangZhou Cotel Co. Ltd.  
     * All right reserved.      
     * UTP服务类.       
     * @author QPING 
     */    
    public class UdpServerSocket {    
        private byte[] buffer = new byte[1024];    
            
        private DatagramSocket ds = null;    
        
        private DatagramPacket packet = null;    
        
        private InetSocketAddress socketAddress = null;    
        
        private String orgIp;    
        
        /**  
         * 构造函数,绑定主机和端口.  
         * @param host 主机  
         * @param port 端口  
         * @throws Exception  
         */    
        public UdpServerSocket(String host, int port) throws Exception {    
            socketAddress = new InetSocketAddress(host, port);    
            ds = new DatagramSocket(socketAddress);    
            System.out.println("服务端启动!");    
        }    
            
        public final String getOrgIp() {    
            return orgIp;    
        }    
        
        /**  
         * 设置超时时间,该方法必须在bind方法之后使用.  
         * @param timeout 超时时间  
         * @throws Exception  
         */    
        public final void setSoTimeout(int timeout) throws Exception {    
            ds.setSoTimeout(timeout);    
        }    
        
        /**  
         * 获得超时时间.  
         * @return 返回超时时间.  
         * @throws Exception  
         */    
        public final int getSoTimeout() throws Exception {    
            return ds.getSoTimeout();    
        }    
        
        /**  
         * 绑定监听地址和端口.  
         * @param host 主机IP  
         * @param port 端口  
         * @throws SocketException  
         */    
        public final void bind(String host, int port) throws SocketException {    
            socketAddress = new InetSocketAddress(host, port);    
            ds = new DatagramSocket(socketAddress);    
        }    
        
        
        /**  
         * 接收数据包,该方法会造成线程阻塞.  
         * @return 返回接收的数据串信息  
         * @throws IOException   
         */    
        public final String receive() throws IOException {    
            packet = new DatagramPacket(buffer, buffer.length);    
            ds.receive(packet);    
            orgIp = packet.getAddress().getHostAddress();    
            String info = new String(packet.getData(), 0, packet.getLength());    
            System.out.println("接收信息:" + info);    
            return info;    
        }    
        
        /**  
         * 将响应包发送给请求端.  
         * @param bytes 回应报文  
         * @throws IOException  
         */    
        public final void response(String info) throws IOException {    
            System.out.println("客户端地址 : " + packet.getAddress().getHostAddress()    
                    + ",端口:" + packet.getPort());    
            DatagramPacket dp = new DatagramPacket(buffer, buffer.length, packet    
                    .getAddress(), packet.getPort());    
            dp.setData(info.getBytes());    
            ds.send(dp);    
        }    
        
        /**  
         * 设置报文的缓冲长度.  
         * @param bufsize 缓冲长度  
         */    
        public final void setLength(int bufsize) {    
            packet.setLength(bufsize);    
        }    
        
        /**  
         * 获得发送回应的IP地址.  
         * @return 返回回应的IP地址  
         */    
        public final InetAddress getResponseAddress() {    
            return packet.getAddress();    
        }    
        
        /**  
         * 获得回应的主机的端口.  
         * @return 返回回应的主机的端口.  
         */    
        public final int getResponsePort() {    
            return packet.getPort();    
        }    
        
        /**  
         * 关闭udp监听口.  
         */    
        public final void close() {    
            try {    
                ds.close();    
            } catch (Exception ex) {    
                ex.printStackTrace();    
            }    
        }  
    }
        

    此时,主函数处代码调用:

    package com.swust.udp;
    
    public class udpServer {     
    
        /**  
         * 测试方法.  
         * @param args  
         * @throws Exception  
         */    
         public static void main(String[] args) throws Exception  {   
            String serverHost = "127.0.0.1";    
            int serverPort = 3344;    
            UdpServerSocket udpServerSocket = new UdpServerSocket(serverHost, serverPort);  
            while (true) {    
                udpServerSocket.receive();    
                udpServerSocket.response("你好,paopao,已收到!");    
                    
            }    
        }    
    }   


    相应的,客户端代码:

    新建udpClient.java ,udpClient类代码:

    package com.swust.udp;
    
    import java.io.*;    
    import java.net.*;    
        
    /**  
     * Copyright 2007 GuangZhou Cotel Co. Ltd.  
     * All right reserved.      
     * UDP客户端程序,用于对服务端发送数据,并接收服务端的回应信息.  
     * @author QPING 
     */    
    public class UdpClientSocket {    
        private byte[] buffer = new byte[1024];    
        
        private DatagramSocket ds = null;    
        
        /**  
         * 构造函数,创建UDP客户端  
         * @throws Exception  
         */    
        public UdpClientSocket() throws Exception {    
            ds = new DatagramSocket();    
        }    
            
        /**  
         * 设置超时时间,该方法必须在bind方法之后使用.  
         * @param timeout 超时时间  
         * @throws Exception  
         */    
        public final void setSoTimeout(final int timeout) throws Exception {    
            ds.setSoTimeout(timeout);    
        }    
        
        /**  
         * 获得超时时间.  
         * @return 返回超时时间  
         * @throws Exception  
         */    
        public final int getSoTimeout() throws Exception {    
            return ds.getSoTimeout();    
        }    
        
        public final DatagramSocket getSocket() {    
            return ds;    
        }    
        
        /**  
         * 向指定的服务端发送数据信息.  
         * @param host 服务器主机地址  
         * @param port 服务端端口  
         * @param bytes 发送的数据信息  
         * @return 返回构造后俄数据报  
         * @throws IOException  
         */    
        public final DatagramPacket send(final String host, final int port,    
                final byte[] bytes) throws IOException {    
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress    
                    .getByName(host), port);    
            ds.send(dp);    
            return dp;    
        }    
        
        /**  
         * 接收从指定的服务端发回的数据.  
         * @param lhost 服务端主机  
         * @param lport 服务端端口  
         * @return 返回从指定的服务端发回的数据.  
         * @throws Exception  
         */    
        public final String receive(final String lhost, final int lport)    
                throws Exception {    
            DatagramPacket dp = new DatagramPacket(buffer, buffer.length);    
            ds.receive(dp);    
            String info = new String(dp.getData(), 0, dp.getLength());    
            return info;    
        }    
        
        /**  
         * 关闭udp连接.  
         */    
        public final void close() {    
            try {    
                ds.close();    
            } catch (Exception ex) {    
                ex.printStackTrace();    
            }    
        }    
    }

    此时,客户端主函数:

    package com.swust.udp;
    
    public class udpClient {
        /**  
         * 测试客户端发包和接收回应信息的方法.  
         * @param args  
         * @throws Exception  
         */    
        public static void main(String[] args) throws Exception {    
            UdpClientSocket client = new UdpClientSocket();    
            String serverHost = "127.0.0.1";    
            int serverPort = 3344;    
            client.send(serverHost, serverPort, ("你好,服务器你一直在运行啊
    NB!").getBytes());    
            String info = client.receive(serverHost, serverPort);    
            System.out.println("服务端回应数据:" + info);    
        }    
    }   

                                                                                                                                                  2015-08-21于大学

  • 相关阅读:
    穷举法和搜索法的统计三角形
    2015.5.21 Core Java Volume 1
    我喜欢出发
    MeshLab中画面在前面加个f的代码
    【axel帮助代码】为了在单位正方形里面画一个洞 ,网上获取了此代码。
    uniapp 发起网络请求
    qt 取进程列表,读写内存, 写字节集
    qt 注册热键
    qt 获取窗口句柄的线程id和进程id GetWindowThreadProcessId
    qt 向窗口发送消息,键盘输入事件
  • 原文地址:https://www.cnblogs.com/shuqingstudy/p/4749194.html
Copyright © 2011-2022 走看看