网络通信学习笔记(四)---UDP通信

2021-01-13 17:40:49 浏览数 (1)

1. UDP协议

这里我们首先需要明白一点,UDP本身就是一种不需要连的协议,所以是不存在客户端与服务端的.

我们通常是通过发送方与接收方的概念来区分,但是我们又需要明白一点发送方与接收方可能是同一个机器.

1.1 UDP消息发送1.0

这里我们还是通过代码来讲解,并且这里我们还是分两个部分来讲.

一是发送方,另一个就是接收方

发送方:

代码语言:javascript复制
  public static void main(String[] args) throws Exception {
        //建立一个DatagramSocket对象,这里同时我们也开放他的6666端口号,只要开放端口号之后就不存在是发送方还是接收方的概念了,既可以是发送方,也可以是接收方.
        DatagramSocket socket=new DatagramSocket(6666);
        //发送的信息
        String msg="你好啊,服务器!";
        //发送的对象的ip地址以及端口号
        InetAddress localhost=InetAddress.getByName("localhost");
        int port=9999;
        //发送的数据报的各类信息,数据的起始位置,接收方的ip及端口号
        DatagramPacket packet=new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhost,port);
        //发送数据报
        socket.send(packet);
    }

接收方:

代码语言:javascript复制
public static void main(String[] args) throws Exception{
        //开放端口
        DatagramSocket socket=new DatagramSocket(9999);
        //接收数据报
        byte[]buffer=new byte[1024];
        DatagramPacket packet=new DatagramPacket(buffer,0,buffer.length);
        //阻塞接受将信息存入到packet对象之中
        socket.receive(packet);
        //打印数据
        System.out.println(packet.getAddress().getHostAddress());
        System.out.println(new String(packet.getData(),0,packet.getLength()));
        //关闭连接
        socket.close();

    }

其实从上面我们也能够看出来UDP就是不需要连接的,因为整个的过程中我们都没有看到ServerSocket这个对象,而是通过 DatagramSocket 这个对象来进行.

其次就是之前我们都是通过 流的形式 来进行数据的传输,但是在UDP中我们则是通过 数据报 的形式来进行,这里其实如果大家学过计算机网络这门课程的话,应该就懂了.

实际效果:

1.2 UDP消息发送2.0

上面的是我们只能在程序中规定好消息,然后发送,并且整个过程是一次性的,程序执行完就没有了,现在我们编写的就是能够通过键盘输入并且传递信息,并且接收能够持续接受信息,只有当接收到bye这样一个关键字时,我们才退出整个程序.

发送方:

代码语言:javascript复制
public static void main(String[] args) throws Exception {
        DatagramSocket socket=new DatagramSocket(9999);
        while (true){
            BufferedReader Reader=new BufferedReader(new InputStreamReader(System.in));
            String data= Reader.readLine();
            byte [] bytes=data.getBytes();
            DatagramPacket packet=new DatagramPacket(bytes,0,bytes.length,new InetSocketAddress("localhost",8888));
            socket.send(packet);
            if(data.equals("bye"))
                break;
        }
        socket.close();
    }

接收方:

代码语言:javascript复制
 public static void main(String[] args) throws Exception {
        DatagramSocket socket=new DatagramSocket(8888);
        while (true){
            byte[] bytes=new byte[1024];
            DatagramPacket packet=new DatagramPacket(bytes,0,bytes.length);//阻塞式接收包裹
            socket.receive(packet);
            byte[]newdata=packet.getData();
            String data=new String(newdata,0,newdata.length);
            System.out.println(data);
            if(data.equals("bye"))
                break;
        }
        socket.close();
    }

实际效果:

1.3 UDP多线程聊天

这里我们会运用到多线程的理念,如果有不了解的建议先去了解一下之后再来学习.

这里我们主要为发送方与接收方两个角色各创建一个线程

TalkSend

代码语言:javascript复制
public class TalkSend implements Runnable {
    DatagramSocket socket=null;
    BufferedReader Reader=null;
    private String toip;
    private int fromport;
    private int toport;

    public TalkSend(String toip, int fromport, int toport) throws Exception {
        this.toip = toip;
        this.fromport = fromport;
        this.toport = toport;
        socket=new DatagramSocket(fromport);
        Reader=new BufferedReader(new InputStreamReader(System.in));
    }
    @Override
    public void run() {
        while (true){
            try {
                String data= Reader.readLine();
                byte [] bytes=data.getBytes();
                DatagramPacket packet=new DatagramPacket(bytes,0,bytes.length,new InetSocketAddress(this.toip,this.toport));
                socket.send(packet);
                if(data.equals("bye"))
                    break;
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        socket.close();
    }
}

TalkReceive

代码语言:javascript复制
public class TalkReceive implements Runnable {
    DatagramSocket socket=null;
    private String msgfrom;
    private int port;
    public TalkReceive(String msgfrom,int port) throws SocketException {
        this.msgfrom=msgfrom;
        this.port = port;
        socket=new DatagramSocket(port);
    }
    @Override
    public void run() {
        while (true){
            try {
                byte[] bytes=new byte[1024];
                DatagramPacket packet=new DatagramPacket(bytes,0,bytes.length);
                socket.receive(packet);
                byte[]newdata=packet.getData();
                String data=new String(newdata,0,newdata.length);
                System.out.println(msgfrom ":" data);
                if(data.equals("bye"))
                    break;
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        socket.close();
    }
}

创建完发送与接收线程之后,我们就可以创建学生与老师两个用户来实现这个聊天程序.

学生:

代码语言:javascript复制
public class TalkStudent {
    public static void main(String[] args) throws Exception {
        new Thread(new TalkSend("localhost",7777,9999)).start();
        new Thread(new TalkReceive("老师",8888)).start();
    }
}

教师:

代码语言:javascript复制
public class TalkTeacher {
    public static void main(String[] args) throws Exception {
        new Thread(new TalkSend("localhost",5555,8888)).start();
        new Thread(new TalkReceive("学生",9999)).start();
    }
}

这里我们只需要稍微注意一下端口号的对应就行了

实际效果:

这里出现中文乱码主要是因为cmd是通过GBK来进行编码的,这里可以自己去设置成UTF-8的编码方式.

都看到这儿了,如果觉得对你有帮助的话,可以关注我的公众号,坚持日更技术好文章.

0 人点赞