JAVA用UDP实现通信

本人小白,最近工作用到UDP学习记录一下

相关方法简单说明

java里udp的通信是由UdpServiceSocket 这个类实现的

发送:

如果你想向外发送一个信息需要以下几个方法:

 DatagramSocket socket = new DatagramSocket();//实例化对象
        String serverHost = "127.0.0.1";//地址
        int serverPort = 3344;//端口
        DatagramPacket dp = new DatagramPacket((name).getBytes(), (name).getBytes().length,
            InetAddress.getByName(serverHost), serverPort);//向地址端口发送包
        socket.send(dp);//发送
接收
DatagramSocket socket = new DatagramSocket(3344);//实例化对象指定监听端口号
byte[] buf =new byte[1024];
DatagramPacket p = new DatagramPacket(buf,buf.length);
socket.receive(p);//p里面就有接收到的内容了 该方法会造成阻塞
int port = p.getPort();//对方端口号
String address = p.getAddress().toString();//船端地址(多个/)
String message= new String(p.getData()).trim();//信息    getData()取得报文的byte数组编码
关于DatagramPacket
DatagramPacket(byte[] buf, int length, InetAddress addr, int port):从buf数组中,取出length长的数据创建数据包对象,目标是addr地址,port端口。 
DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port):从buf数组中,取出offset开始的、length长的数据创建数据包对象,目标是addr地址,port端口。 
DatagramPacket(byte[] buf, int offset, int length):将数据包中从offset开始、length长的数据装进buf数组。
DatagramPacket(byte[] buf, int length):将数据包中length长的数据装进buf数组。 

简单实例:

package com.zzm.test.vast.socket;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class SimpleDemo {

    public static void receive(){
        new Thread(){

            @Override
            public void run() {
                DatagramSocket socket =null;
                try {
                    System.out.println("开启服务。。。");
                    socket = new DatagramSocket(3344);
                    byte[] buffer = new byte[1024];
                    DatagramPacket p = new DatagramPacket(buffer, buffer.length);
                    System.out.println("开始开启监听。。。");
                    socket.receive(p);//不断监听的话可以放到while循环中
                    byte[] data = new byte[p.getLength()];
                    int port = p.getPort();//对方端口号
                    String address = p.getAddress().toString();//船端地址(多个/)
                    String message= new String(p.getData()).trim();//信息    getData()取得报文的byte数组编码
                    System.out.println("Receiver:接收到来自"+address+"端口:"+port+"的消息:" + message);
                    socket.close();
                    System.out.println("接收完毕关闭receive服务。。。。");
                } catch (Exception e) {
                    e.printStackTrace();
                }finally{
                    if(null!=socket){
                        socket.close();
                    }
                }


            }

        }.start();
    }

    public static void send(){
        new Thread(){

            @Override
            public void run() {
                DatagramSocket socket =null;
                try {
                    socket = new DatagramSocket();
                    String serverHost = "127.0.0.1";//目标地址是本地地址
                    int serverPort = 3344;//目标端口
                    DatagramPacket dp = new DatagramPacket(("你好 recevier").getBytes(), ("你好 recevier").getBytes().length,
                        InetAddress.getByName(serverHost), serverPort);
                    System.out.println("sender:发送消息。。。。");
                    socket.send(dp);//发送消息时随机选择端口
                } catch (Exception e) {
                    e.printStackTrace();
                }finally{
                    if(null!=socket){
                        socket.close();
                        System.out.println("发送完毕,关闭send服务");
                    }
                }

            }

        }.start();
    }

    public static void main(String[] args) {
        receive();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        send();
    }

}
控制台输出:
开启服务。。。
开始开启监听。。。
sender:发送消息。。。。
Receiver:接收到来自/127.0.0.1端口:61145的消息:你好 recevier
发送完毕,关闭send服务
接收完毕关闭receive服务。。。。

以下可忽略

本人代码未完待续。。。(由于针对工作的要求是这个么写的:多个地址会向服务端发自己名字,服务端要选择名字向对应的发消息,新手写的不好互喷,大神直接跳过。。)

服务端:可以接受多个客户端发的请求建立连接

public class UdpServiceSocket {

    private  DatagramSocket socket ;

    private Map<String,String[]> ships = new ConcurrentHashMap<String,String[]>();//存放接收到的地址端口号

    private boolean flag = false;//是否在循环接受船端信息 true-是,flase-否

    Logger logger = LoggerFactory.getLogger(UdpServiceSocket.class);

    public void setSocket(DatagramSocket socket) {
        logger.info("UdpServiceSocket 设定 DatagramSocket :"+socket+"........");
        this.socket = socket;
    }

    public UdpServiceSocket() {
    }

    public UdpServiceSocket(int port) {
        try {
            socket = new DatagramSocket(port);
        } catch (SocketException e) {
            logger.error("socket初始化失败。。。",e);
        }
    }

    public Map<String, String[]> getShips() {
        return ships;
    }

    public void setShips(Map<String, String[]> ships) {
        this.ships = ships;
    }

    public void receive(){
        logger.info("开始开启socket接受服务接受信息。。。");
        if(null==socket){
            logger.error("socket未初始化,开启接受信息失败。。。");
            return;
        }
        flag = true;
        new Thread(){
            @Override
            public void run() {

                try {
                    logger.info("开始接收信息。。。");
                    while(flag){
                        byte[] buf =new byte[1024];
                        DatagramPacket p = new DatagramPacket(buf,buf.length);
                        socket.receive(p);
                        String port = String.valueOf(p.getPort());//端口号
                        String address = p.getAddress().toString();//地址
                        if(address.startsWith("/")){
                            address = address.substring(1);
                        }
                        String shipName = new String(p.getData()).trim();//名
                    //  if(null==ships.get(shipName)){
                            ships.put(shipName, new String[]{address,port});
                    //  }
                        logger.info("接收到一条信息。。。"+shipName+" "+ships.get(shipName)[0]+" "+ships.get(shipName)[1]);
                    }
                } catch (IOException e) {
                    logger.error("接受信息异常(可能由close关闭引起)",e);
                }
            }
        }.start();
    }

    public void send(String shipName,String message){
        if(null==socket){
            logger.error("socket没有初始化,发送信息失败。。。");
            return;
        }
        new Thread(){
            @Override
            public void run() {
                try{
                    logger.info("开始发送信息到。。。");
                    logger.info("查询目标:"+shipName+"的信息。。。");
                    String[] ship = ships.get(shipName);
                    String address = null;
                    String port = null;
                    if(null!=ship&&ship.length==2){
                        address = ship[0];
                        port = ship[1];
                    }else{
                        logger.info("查询无该ip端口信息 ship:"+ship+"发送终止");
                        return;
                    }
                    DatagramPacket dp = new DatagramPacket(message.getBytes(), message.getBytes().length,
                            InetAddress.getByName(address), Integer.valueOf(port));
                    socket.send(dp);
                    logger.info("向"+shipName+"信息发送完毕。。。");
                    return;
                }catch(Exception e){
                    logger.error("发送信息到"+shipName+"失败,服务异常",e);
                    return;
                }
            }

        }.start();
    }

    public void close(){
        logger.info("关闭接受信息服务。。。");
        stopReceive();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            logger.error("线程sleep异常"+e);
        }
        if(null!=socket){
            try{
                socket.close();
            }catch(Exception e){
                logger.info("关闭服务,receive可能报错",e);
            }
            ships.clear();
        }
        logger.info("关闭接受信息服务成功。。。");
    }

    public boolean isclosed(){
        if(null==socket){
            return true;
        }
        return socket.isClosed();
    }

    public void stopReceive(){//停止循环receive
        flag = false;
    }

    public void startReceive(){
        receive();
    }
    public boolean isreceive(){//是否循环receive信息中
        return flag;
    }
    /**
 * 启动服务并开始接收
     * @param port
     */
    public void start(int port){
        try {
            socket = new DatagramSocket(port);
            receive();//开始收接
        } catch (SocketException e) {
            logger.error("初始化socket失败。。。",e);
        }
    }
    /**
     * 手动添加
     * @param shipName
     * @param address
     * @param port
     */
    public void addShip(String shipName,String address,String port){
        ships.put(shipName, new String[]{address,port});
    }
    public void clearShips(){
        ships.clear();
    }
    public String getPort(){
        if(socket==null){
            return "";
        }
        return String.valueOf(socket.getLocalPort());
    }
    public static void main(String[] args) throws InterruptedException{//测试用
        UdpServiceSocket s = new UdpServiceSocket();
        s.start(3344);
//      ships.put("hi", new String[]{"127.0.0.1","3344"});
//      s.setShips(ships);
        while(true){
            Thread.sleep(3000);
            s.send("a", "13123131");
            s.send("b", "2134234");
//          s.send("hi", "message from server");
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值