Java 日看一类(60)之net包中的AbstractPlainDatagramSocketImpl类

本文解析了一个非公共类的内部实现,该类用于抽象数据报和组播套接字的功能,介绍了其成员变量、方法及操作权限设置等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

该类引入了如下包:

import java.io.FileDescriptor;
import java.io.IOException;
import java.security.AccessController;
import sun.net.ResourceManager;


该类继承自DatagramSocketImpl类

该类不是公共类



该类的类头注释如下:

/**
 * Abstract datagram and multicast socket implementation base class.
 * Note: This is not a public class, so that applets cannot call
 * into the implementation directly and hence cannot bypass the
 * security checks present in the DatagramSocket and MulticastSocket
 * classes.
 *
 * @author Pavani Diwanji
 */

大意如下:

该类是数据报和组播的基础实现类。

注意:该类不是公共类,所以applets不能直接调用该实现并且因此不能避过在DatagramSocket和MulticastSocket的即时安全性检查



该类含有如下的成员变量:

超时记录(等ack

int timeout = 0;

连接状态

boolean connected = false;

服务类型

private int trafficClass = 0;

目的地址

protected InetAddress connectedAddress = null;

目的端口

private int connectedPort = -1;

本地主机名

private static final String os = AccessController.doPrivileged(//跳过权限检查
    new sun.security.action.GetPropertyAction("os.name")
);

检测连接是否被禁用(看主机名里是不是有OS X,我本人用的Mac os,所以检测的是OS X),如果为false,native函数connect不能调用

private final static boolean connectDisabled = os.contains("OS X");



该类含有如下的成员方法:

默认构造函数

protected synchronized void create() throws SocketException {
    ResourceManager.beforeUdpCreate();//资源管理器检查创建UDP的资源
    fd = new FileDescriptor();//创建文件描述符
    try {
        datagramSocketCreate();//尝试创建DatagramSocket
    } catch (SocketException ioe) {
        ResourceManager.afterUdpClose();//出异常关闭的时候也需要进行资源检查,释放资源
        fd = null;
        throw ioe;
    }
}

绑定本地端口

protected synchronized void bind(int lport, InetAddress laddr)
    throws SocketException {
    bind0(lport, laddr);
}

绑定本地端口(native

protected abstract void bind0(int lport, InetAddress laddr)
    throws SocketException;

发送数据报包(需要后续完成,

protected abstract void send(DatagramPacket p) throws IOException;

连接远端的数据报套接字

protected void connect(InetAddress address, int port) throws SocketException {
    connect0(address, port);
    connectedAddress = address;
    connectedPort = port;
    connected = true;
}

断开已有的连接

protected void disconnect() {
    disconnect0(connectedAddress.holder().getFamily());
    connected = false;
    connectedAddress = null;
    connectedPort = -1;
}

窥探包来源(参数就是包来源,不是很懂,等到后面看到该类实例应该就清楚了,返回值肯定是IP地址一类的

protected abstract int peek(InetAddress i) throws IOException;

窥探包来源(返回值是包来源

protected abstract int peekData(DatagramPacket p) throws IOException;

接收数据报

protected synchronized void receive(DatagramPacket p)
    throws IOException {
    receive0(p);
}

接收数据报(native

protected abstract void receive0(DatagramPacket p)
    throws IOException;

设置发包过期时间(ttl

protected abstract void setTimeToLive(int ttl) throws IOException;

返回设置的过期时间(int

protected abstract int getTimeToLive() throws IOException;

设置发包过期时间(emmm,参数是byte类

protected abstract void setTTL(byte ttl) throws IOException;

返回设置的过期时间(byte

protected abstract byte getTTL() throws IOException;

加入组播团体

protected void join(InetAddress inetaddr) throws IOException {
    join(inetaddr, null);
}

离开组播团体

protected void leave(InetAddress inetaddr) throws IOException {
    leave(inetaddr, null);
}

加入组播团体(参数不同

protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
    throws IOException {
    if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
        throw new IllegalArgumentException("Unsupported address type");
    join(((InetSocketAddress)mcastaddr).getAddress(), netIf);
}

加入组播团体(基础方法

protected abstract void join(InetAddress inetaddr, NetworkInterface netIf)
    throws IOException;

离开组播团体

protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
    throws IOException {
    if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
        throw new IllegalArgumentException("Unsupported address type");
    leave(((InetSocketAddress)mcastaddr).getAddress(), netIf);
}

基础方法

protected abstract void leave(InetAddress inetaddr, NetworkInterface netIf)
    throws IOException;

关闭套接字

protected void close() {
    if (fd != null) {//文件描述符标志该套接字状态
        datagramSocketClose();
        ResourceManager.afterUdpClose();
        fd = null;
    }
}

判定当前套接字状态

protected boolean isClosed() {
    return (fd == null) ? true : false;
}

最终操作(关闭

protected void finalize() {
    close();
}

设置操作权限(object 根据设置操作不同而不同,该方法主要是检查,设置封装在另一个方法里

public void setOption(int optID, Object o) throws SocketException {
    if (isClosed()) {//检测当前套接字是否关闭
        throw new SocketException("Socket Closed");
    }
    switch (optID) {//常量声明在父类
       /* check type safety b4 going native.  These should never
        * fail, since only java.Socket* has access to
        * PlainSocketImpl.setOption().
        */
    case SO_TIMEOUT://设置超时
        if (o == null || !(o instanceof Integer)) {
            throw new SocketException("bad argument for SO_TIMEOUT");
        }
        int tmp = ((Integer) o).intValue();
        if (tmp < 0)
            throw new IllegalArgumentException("timeout < 0");
        timeout = tmp;
        return;
    case IP_TOS://IP服务类型设置
        if (o == null || !(o instanceof Integer)) {
            throw new SocketException("bad argument for IP_TOS");
        }
        trafficClass = ((Integer)o).intValue();
        break;
    case SO_REUSEADDR://地址端口重用
        if (o == null || !(o instanceof Boolean)) {
            throw new SocketException("bad argument for SO_REUSEADDR");
        }
        break;
    case SO_BROADCAST://设置广播
        if (o == null || !(o instanceof Boolean)) {
            throw new SocketException("bad argument for SO_BROADCAST");
        }
        break;
    case SO_BINDADDR://绑定地址
        throw new SocketException("Cannot re-bind Socket");
    case SO_RCVBUF://接收和发送的缓冲大小
    case SO_SNDBUF:
        if (o == null || !(o instanceof Integer) ||
            ((Integer)o).intValue() < 0) {
            throw new SocketException("bad argument for SO_SNDBUF or " +
                                      "SO_RCVBUF");
        }
        break;
    case IP_MULTICAST_IF://组播设置
        if (o == null || !(o instanceof InetAddress))
            throw new SocketException("bad argument for IP_MULTICAST_IF");
        break;
    case IP_MULTICAST_IF2:
        if (o == null || !(o instanceof NetworkInterface))
            throw new SocketException("bad argument for IP_MULTICAST_IF2");
        break;
    case IP_MULTICAST_LOOP:
        if (o == null || !(o instanceof Boolean))
            throw new SocketException("bad argument for IP_MULTICAST_LOOP");
        break;
    default:
        throw new SocketException("invalid option: " + optID);
    }
    socketSetOption(optID, o);
}

获得具体设置信息

public Object getOption(int optID) throws SocketException {
    if (isClosed()) {
        throw new SocketException("Socket Closed");
    }

    Object result;

    switch (optID) {
        case SO_TIMEOUT:
            result = new Integer(timeout);
            break;

        case IP_TOS:
            result = socketGetOption(optID);
            if ( ((Integer)result).intValue() == -1) {
                result = new Integer(trafficClass);
            }
            break;

        case SO_BINDADDR:
        case IP_MULTICAST_IF:
        case IP_MULTICAST_IF2:
        case SO_RCVBUF:
        case SO_SNDBUF:
        case IP_MULTICAST_LOOP:
        case SO_REUSEADDR:
        case SO_BROADCAST:
            result = socketGetOption(optID);
            break;

        default:
            throw new SocketException("invalid option: " + optID);
    }

    return result;
}

创建数据报套接字

protected abstract void datagramSocketCreate() throws SocketException;

关闭数据包套接字

protected abstract void datagramSocketClose();

具体设置

protected abstract void socketSetOption(int opt, Object val)
    throws SocketException;

具体设置获得

protected abstract Object socketGetOption(int opt) throws SocketException;

连接至目的地址和端口

protected abstract void connect0(InetAddress address, int port) throws SocketException;

断开连接

protected abstract void disconnect0(int family);

返回连接禁用状态

protected boolean nativeConnectDisabled() {
    return connectDisabled;
}

检测数据有效性(猜测是进行校验码校验

abstract int dataAvailable();



该类含有如下的静态代码块:

static {
    java.security.AccessController.doPrivileged(
        new java.security.PrivilegedAction<Void>() {//加载运行时的net库
            public Void run() {
                System.loadLibrary("net");
                return null;
            }
        });
}



该类对于学过一些计算机网络知识的人来说比较好理解,对于那些名词(比如,组播、广播、ttl等等)和操作设置都应该会有大致的印象。对于没有学过计算机网络的人而言可能对于这些名词的理解会比较吃力,推荐先去补充基础理论知识。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值