0


基于UDP协议的Java聊天室

    在实现Java聊天室之前,我们先了解一下什么是UDP协议,以及使用UDP协议的客户端或服务器端是如何来接收信息或者发送信息的。

    UPD(User Datagram Protocol)用户数据报协议,是网络模型中的传输层协议。UDP协议是无连接、不可靠的,并且它是面向报文的,并不是像TCP一样,面向字节流的。UDP没有拥塞控制,适合媒体通信。

    在Java.net报中,也提供了两个类DatagramSocket和DatagramPacket来支持UDP的数据报通信。DatagramSocket是用于在程序之间建立传输的通信通道,并且它发送的每个包都需要指定地址。而DatagramPacket是用来表示一个数据包的,DatagramPacket只是在首次创建时指定地址,以后所有的包都会通过DatagramSocket发送。

    UDP编程分为四个部分:建立连接,发送数据,接收数据,关闭连接。

1、在服务器端:使用UDP来监听指定端口。代码如下:

DatagramSocket ds = new DatagramSocket(6666); // 监听指定端口
while (true) { // 无限循环
    // 数据缓冲区:
    byte[] buffer = new byte[1024];
    DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
    ds.receive(packet); // 收取一个UDP数据包
    // 收取到的数据存储在buffer中,由packet.getOffset(), packet.getLength()指定起始位置和长度
    // 将其按UTF-8编码转换为String:
    String s = new String(packet.getData(), packet.getOffset(), packet.getLength(), StandardCharsets.UTF_8);
    // 发送数据:
    byte[] data = "ACK".getBytes(StandardCharsets.UTF_8);
    packet.setData(data);
    ds.send(packet);
}

2、服务器首先使用如下语句在指定端口监听UDP数据包:

// 监听6666端口
DatagramSocket ds = new DatagramSocket(6666);

3、 要接收一个数据包,需要准备一个byte[] 类型数组缓冲区,并通过DatagramPacket实现接收:

byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
ds.receive(packet);

4、如果我们收到的是String类型,则通过DatagramPacket返回的packet.getOfferset()和packet.getLength()确定数据在缓冲区的起止位置:

String s = new String(packet.getData(), packet.getOffset(), packet.getLength(), StandardCharsets.UTF_8);

5、当服务器收到一个UDP数据包后,通常会立刻回复一个UDP包:

byte[] data = ...
packet.setData(data);
ds.send(packet);

6、 而在客户端,只需要直接使用socket发送一个数据包,等待服务器响应一个数据包即可:

DatagramSocket ds = new DatagramSocket();
ds.setSoTimeout(1000);
ds.connect(InetAddress.getByName("localhost"), 6666); // 连接指定服务器和端口

// 发送:
byte[] data = "Hello".getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length);
ds.send(packet);

// 接收:
byte[] buffer = new byte[1024];
packet = new DatagramPacket(buffer, buffer.length);
ds.receive(packet);
String resp = new String(packet.getData(), packet.getOffset(), packet.getLength());
ds.disconnect();

7、客户端打开一个socket:

DatagramSocket ds = new DatagramSocket();
ds.setSoTimeout(1000);
ds.connect(InetAddress.getByName("localhost"), 6666);

8、客户端实例时候,不需要指定端口,操作系统会指定一个当前未使用的端口,然后调用setSoTime(3000),设定超时时间。如果超时没有收到数据包,则会自动断开与当前服务器的连接。

9、如果客户端认为通信结束了,就可以调用disconnect()断开连接。disconnect()方法只是清楚了发送到服务器端的IP和端口。以便于socket连接下一台服务器。



下面展示基于UDP协议的Java聊天室:

代码展示(服务器端 or 客户端1):

package com.apesource;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

import javax.xml.crypto.Data;

public class ChatA {
    public static void main(String[] args) {
        // 控制台上输入
        Scanner scan = new Scanner(System.in);
        
        // 创建DatagramSocket的对象,自身端口为1097
        try (DatagramSocket socket = new DatagramSocket(1097)) {
        
            // 创建DatagramPacket对象,同时监控客户端8888端口
            DatagramPacket sendPacket = new DatagramPacket(new byte[1024], 1024,new InetSocketAddress("192.168.254.146", 8888));
            DatagramPacket receivePacket = new DatagramPacket(new byte[1024],1024);

            while(true) {
            // 发送
            System.out.print("服务器端说:");    
            String str = scan.nextLine();
            if(str.equals("退出聊天")) {
                String res = "对方已经退出聊天室!";
                byte[] sendContent = res.getBytes();
                sendPacket.setData(sendContent);
                socket.send(sendPacket);
                break;
            }

            // 接收
            socket.receive(receivePacket);
            String receiveContent = new String(receivePacket.getData(),receivePacket.getOffset(),receivePacket.getLength());
            System.out.print("客户端说:" + receiveContent);
            System.out.println();
            
            }
        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
    }
}

代码展示(服务器端 or 客户端2):

package com.apesource;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.Scanner;

public class ChatB {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        
        // 自身端口8888
        try (DatagramSocket socket = new DatagramSocket(8888)) {
            DatagramPacket sendPacket = new DatagramPacket(new byte[1024], 1024,new InetSocketAddress("192.168.254.146", 1097));
            DatagramPacket receivePacket = new DatagramPacket(new byte[1024],1024);
            
            while(true) {
            // 接收
            socket.receive(receivePacket);
            String receiveContent = new String(receivePacket.getData(),receivePacket.getOffset(),receivePacket.getLength());
            System.out.print("服务器端说:" + receiveContent);
            System.out.println();
            
            
            // 发送
            System.out.print("客户端说:");
            String str = scan.nextLine();
            if(str.equals("退出聊天")) {
                String res = "对方已退出聊天室!";
                byte[] sendContent = res.getBytes();
                sendPacket.setData(sendContent);
                socket.send(sendPacket);
                break;
            }
            byte[] sendContent = str.getBytes();
            sendPacket.setData(sendContent);
            socket.send(sendPacket);
            }
        
            
        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
    

标签: javase java udp

本文转载自: https://blog.csdn.net/qq_17845335/article/details/125822710
版权归原作者 卡多希y 所有, 如有侵权,请联系我们删除。

“基于UDP协议的Java聊天室”的评论:

还没有评论