Socket套接字(UDP数据报)篇

概念

Socket套接字,是由系统提供用于网络通信的技术,是基于TCP/IP协议的网络通信的基本操作单元.
基于Socket套接字的网络程序开发就是网络编程.

数据报套接字

使用的是UDP(User Datagram Protocol)协议,传输层协议.

  • 无连接
  • 不可靠传输
  • 面向数据报
  • 全双工

对于UDP协议来说,具有无连接,面向数据报的特征,每次都是没有建立连接,并且一次性发送全部数据报,并一次性接收全部数据报.
java使用UDP协议通信,基于DatagramSocket类创建数据报套接字,并使用DatagramPacket作为发送或接收的UDP数据报.

DatagramSocket

DatagramSocket是UDP Socket,用于发送和接收UDP数据报.

DatagramSocket构造方法:

方法签名方法说明
DatagramSocket()创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口(一般用于客户端)
DatagramSocket(int port)创建一个UDP数据报套接字的Socket,绑定到指定端口(一般用于服务器端)

DatagramSocket方法:

方法签名方法说明
void receive(DatagramSocket p)就收套接字数据报,没有则会阻塞等待
void send(DatagramSocket p)发送套接字数据报
void close()关闭数据报套接字

DatagramPacket

DatagramPacket是UDP Socket发送和接受的数据报

DatagramPacket构造方法:

方法签名方法说明
DatagramPacket(byte[] buf, int length)这是接收数据报,接收的数据保存在byte数组中,指定接收长度
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address)这是发送数据报,发送的数据时字节数组,从0到指定长度,address指定目的主机的IP和端口号

DatagramPacket方法:

方法签名方法说明
InetAddress getAddress()从接受的数据报中,获取发送端主机IP地址.或者从发送的数据报中,获取接收端主机的IP地址
int getPort()从接受的数据报中,获取发送端主机的端口号.或者从发送的数据报中,获取接收端主机的端口号
byte[] getData()获取数据报中的数据

InetSocketAddress

InetSocketAddress(SocketAddress的子类) 构造方法:

方法签名方法说明
InetSocketAddress(InetAddress addr, int port)创建一个Socket地址,包含IP地址和端口号

下面写一个回显服务器案例供参考:

// 服务器
public class UdpEchoServer {
    private DatagramSocket socket = null;
    public UdpEchoServer(int port) throws SocketException {
        // 根据端口号构造, 端口号被占用的时候,会报错
        socket = new DatagramSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动");
        while (true) {
            // 反复的,长期的反应客户端的请求处理的逻辑
            // 1. 读取请求,并解析。
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(requestPacket);
            // 后续客户端必须发送文本文件,才能这样转字符串
            String request = new String(requestPacket.getData(),0, requestPacket.getLength());
            // 2. 根据请求,计算相应
            String response = process(request);
            // 3. 把响应返回给客户端
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),0,response.getBytes().length,
                    requestPacket.getSocketAddress());
            socket.send(responsePacket);
            System.out.printf("[%s:%d] req: %s, resp: %s\n", requestPacket.getAddress().toString(),requestPacket.getPort(),
                    request,response);
        }
    }

    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server = new UdpEchoServer(999);
        server.start();
    }
    
}

相信仔细看完的小伙伴注意到了,socket对象并没有调用close来关闭,因为此时整个程序
只有一个socket,这个对象的生命周期非常长,是跟随整个程序的.
socket对象->系统中的socket文件->文件描述符
进程结束,就把pcb回收了,文件描述符也随之销毁了.
但是如果有多个socket对象,需要频繁创建释放,一定要去进行close操作.

// 客户端
public class UDPEchoClient {
    private DatagramSocket socket = null;

    private String serverIp;
    private int serverPort;

    public UDPEchoClient(String ip, int port) throws SocketException {
        this.serverIp = ip;
        this.serverPort = port;
        // 随机端口号
        socket = new DatagramSocket();
    }

    // 让客户端反复地读取控制台内容,把内容构造成UDP请求,发给服务器
    public void start() throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("客户端启动");
        while (true) {
            // 1.从控制台输入
            System.out.println("-> ");
            String request = scanner.nextLine();
            // 2.构造请求对象,发给服务器
            // 使用InetAddress的静态方法,getByName来进行构造(工厂模式)
            // InetAddress.getByName(serverIp),serverPort): 要发送的ip和端口
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),0,request.getBytes().length,
                    InetAddress.getByName(serverIp),serverPort);
            socket.send(requestPacket);
            // 3.客户端读取响应
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(responsePacket);
            String response = new String(responsePacket.getData(),0, responsePacket.getLength());
            // 4. 显示到屏幕上
            System.out.println(response);
        }
    }

    public static void main(String[] args) throws IOException {
    	// 端口号和服务器端一致
        UDPEchoClient client = new UDPEchoClient("127.0.0.1", 999);
        client.start();
    }
}

在这里插入图片描述

小结

本次总结了UDP套接字数据报的相关内容,TCP套接字放到下一章博客中.
希望有收获的小伙伴多多支持.

  • 18
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值