java.lang.Object java.net.DatagramSocket
public class DatagramSocket
此类表示用来发送和接收数据报包的套接字。
数据报套接字是包投递服务的发送或接收点。每个在数据报套接字上发送或接收的包都是单独编址和路由的。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。
在 DatagramSocket 上总是启用 UDP 广播发送。为了接收广播包,应该将 DatagramSocket 绑定到通配符地址。在某些实现中,将 DatagramSocket 绑定到一个更加具体的地址时广播包也可以被接收。
示例:DatagramSocket s = new DatagramSocket(null); s.bind(new InetSocketAddress(8888));
这等价于:DatagramSocket s = new DatagramSocket(8888);
两个例子都能创建能够在 UDP 8888 端口上接收广播的 DatagramSocket。
DatagramPacket
,
DatagramChannel
构造方法摘要 | |
---|---|
|
DatagramSocket() 构造数据报套接字并将其绑定到本地主机上任何可用的端口。 |
protected |
DatagramSocket(DatagramSocketImpl impl) 创建带有指定 DatagramSocketImpl 的未绑定数据报套接字。 |
|
DatagramSocket(int port) 创建数据报套接字并将其绑定到本地主机上的指定端口。 |
|
DatagramSocket(int port, InetAddress laddr) 创建数据报套接字,将其绑定到指定的本地地址。 |
|
DatagramSocket(SocketAddress bindaddr) 创建数据报套接字,将其绑定到指定的本地套接字地址。 |
方法摘要 | |
---|---|
void |
bind(SocketAddress addr) 将此 DatagramSocket 绑定到特定的地址和端口。 |
void |
close() 关闭此数据报套接字。 |
void |
connect(InetAddress address, int port) 将套接字连接到此套接字的远程地址。 |
void |
connect(SocketAddress addr) 将此套接字连接到远程套接字地址(IP 地址 + 端口号)。 |
void |
disconnect() 断开套接字的连接。 |
boolean |
getBroadcast() 检测是否启用了 SO_BROADCAST。 |
DatagramChannel |
getChannel() 返回与此数据报套接字关联的唯一 DatagramChannel 对象(如果有)。 |
InetAddress |
getInetAddress() 返回此套接字连接的地址。 |
InetAddress |
getLocalAddress() 获取套接字绑定的本地地址。 |
int |
getLocalPort() 返回此套接字绑定的本地主机上的端口号。 |
SocketAddress |
getLocalSocketAddress() 返回此套接字绑定的端点的地址,如果尚未绑定则返回 null 。 |
int |
getPort() 返回此套接字的端口。 |
int |
getReceiveBufferSize() 获取此 DatagramSocket 的 SO_RCVBUF 选项的值,该值是平台在 DatagramSocket 上输入时使用的缓冲区大小。 |
SocketAddress |
getRemoteSocketAddress() 返回此套接字连接的端点的地址,如果未连接则返回 null 。 |
boolean |
getReuseAddress() 检测是否启用了 SO_REUSEADDR。 |
int |
getSendBufferSize() 获取此 DatagramSocket 的 SO_SNDBUF 选项的值,该值是平台在 DatagramSocket 上输出时使用的缓冲区大小。 |
int |
getSoTimeout() 获取 SO_TIMEOUT 的设置。 |
int |
getTrafficClass() 为从此 DatagramSocket 上发送的包获取 IP 数据报头中的流量类别或服务类型。 |
boolean |
isBound() 返回套接字的绑定状态。 |
boolean |
isClosed() 返回是否关闭了套接字。 |
boolean |
isConnected() 返回套接字的连接状态。 |
void |
receive(DatagramPacket p) 从此套接字接收数据报包。 |
void |
send(DatagramPacket p) 从此套接字发送数据报包。 |
void |
setBroadcast(boolean on) 启用/禁用 SO_BROADCAST。 |
static void |
setDatagramSocketImplFactory(DatagramSocketImplFactory fac) 为应用程序设置数据报套接字实现工厂。 |
void |
setReceiveBufferSize(int size) 将此 DatagramSocket 的 SO_RCVBUF 选项设置为指定的值。 |
void |
setReuseAddress(boolean on) 启用/禁用 SO_REUSEADDR 套接字选项。 |
void |
setSendBufferSize(int size) 将此 DatagramSocket 的 SO_SNDBUF 选项设置为指定的值。 |
void |
setSoTimeout(int timeout) 启用/禁用带有指定超时值的 SO_TIMEOUT,以毫秒为单位。 |
void |
setTrafficClass(int tc) 为从此 DatagramSocket 上发送的数据报在 IP 数据报头中设置流量类别 (traffic class) 或服务类型八位组 (type-of-service octet)。 |
从类 java.lang.Object 继承的方法 |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
构造方法详细信息 |
---|
public DatagramSocket() throws SocketException
如果有安全管理器,则首先使用 0 作为变量来调用其 checkListen
方法,以确保允许该操作。这可能会导致 SecurityException 异常。
SocketException
- 如果套接字不能被打开,或不能将其绑定到指定的本地端口。
SecurityException
- 如果安全管理器存在并且其
checkListen
方法不允许进行该操作。
SecurityManager.checkListen(int)
protected DatagramSocket(DatagramSocketImpl impl)
impl
- 子类希望在 DatagramSocket 上使用的
DatagramSocketImpl 的实例。
public DatagramSocket(SocketAddress bindaddr) throws SocketException
如果地址为 null
,创建未绑定的套接字。
如果有安全管理器,则首先使用套接字中的端口作为变量来调用其 checkListen
方法,以确保允许该操作。这可能会导致 SecurityException 异常。
bindaddr
- 要绑定的本地套接字地址,对于未绑定的套接字为
null
。
SocketException
- 如果套接字不能被打开,或不能将其绑定到指定的本地端口。
SecurityException
- 如果安全管理器存在并且其
checkListen
方法不允许进行该操作。
SecurityManager.checkListen(int)
public DatagramSocket(int port) throws SocketException
如果存在安全管理器,则首先使用 port
参数作为参数调用其 checkListen
方法,以确保允许该操作。这可能会导致 SecurityException 异常。
port
- 要使用的端口。
SocketException
- 如果套接字不能被打开,或不能将其绑定到指定的本地端口。
SecurityException
- 如果安全管理器存在并且其
checkListen
方法不允许进行该操作。
SecurityManager.checkListen(int)
public DatagramSocket(int port, InetAddress laddr) throws SocketException
如果存在安全管理器,则首先使用 port
参数作为参数调用其 checkListen
方法,以确保允许该操作。这可能会导致 SecurityException 异常。
port
- 要使用的本地端口
laddr
- 要绑定的本地地址
SocketException
- 如果套接字不能被打开,或不能将其绑定到指定的本地端口。
SecurityException
- 如果安全管理器存在并且其
checkListen
方法不允许进行该操作。
SecurityManager.checkListen(int)
方法详细信息 |
---|
public void bind(SocketAddress addr) throws SocketException
如果地址为 null
,则系统将挑选一个临时端口和一个有效本地地址来绑定套接字。
addr
- 要绑定的地址和端口。
SocketException
- 如果绑定过程中发生错误,或者套接字已经被绑定。
SecurityException
- 如果安全管理器存在并且其
checkListen
方法不允许进行该操作。
IllegalArgumentException
- 如果 addr 是不受此套接字支持的 SocketAddress 子类。
public void connect(InetAddress address, int port)
如果套接字要连接的远程目标不存在或不可到达,并且收到了该地址的目标不可达 ICMP 包,那么后续发送和接收的调用可能会抛出 PortUnreachableException。注意,不能保证一定抛出该异常。
在连接时检查调用者对给定主机和端口的发送和接收数据报权限。当连接建立起来后,接收和发送除了对包和套接字的地址和端口进行匹配外,对传入和传出的包将不再执行任何安全性检查。对于发送操作,如果设置了包的地址并且包的地址和套接字的地址不匹配,则将抛出 IllegalArgumentException。连接到多播地址的套接字只能用于发送包。
address
- 套接字的远程地址。
port
- 套接字的远程端口。
IllegalArgumentException
- 如果地址为 null,或端口超出了范围。
SecurityException
- 如果不允许调用者向此地址和端口发送也不允许从此地址接收数据报。
disconnect()
,
send(java.net.DatagramPacket)
,
receive(java.net.DatagramPacket)
public void connect(SocketAddress addr) throws SocketException
addr
- 远程地址。
SocketException
- 如果连接失败
IllegalArgumentException
- 如果 addr 为 null 或者 addr 是不受此套接字支持的 SocketAddress 子类。
connect(java.net.InetAddress, int)
public void disconnect()
public boolean isBound()
public boolean isConnected()
public InetAddress getInetAddress()
public int getPort()
public SocketAddress getRemoteSocketAddress()
null
。
SocketAddress
,如果尚未连接则返回
null
。
getInetAddress()
,
getPort()
,
connect(SocketAddress)
public SocketAddress getLocalSocketAddress()
null
。
SocketAddress
,如果尚未绑定则返回
null
。
getLocalAddress()
,
getLocalPort()
,
bind(SocketAddress)
public void send(DatagramPacket p) throws IOException
DatagramPacket
包含的信息指示:将要发送的数据、其长度、远程主机的 IP 地址和远程主机的端口号。
如果存在安全管理器,且套接字当前没有连接到远程地址,则此方法首先执行某些安全性检查。首先,如果 p.getAddress().isMulticastAddress()
为 true,则此方法以 p.getAddress()
作为参数调用安全管理器的 checkMulticast
方法。如果该表达式的值为 false,此方法改为调用安全管理器的以 p.getAddress().getHostAddress()
和 p.getPort()
为参数的 checkConnect
方法。如果不允许该操作,则每次调用安全管理器方法都会导致 SecurityException。
p
- 将要发送的
DatagramPacket
。
IOException
- 如果发生 I/O 错误。
SecurityException
- 如果安全管理器存在并且其
checkMulticast
或
checkConnect
方法不允许进行发送。
PortUnreachableException
- 套接字连接到当前不可达的目标时可能抛出。注意,不能保证一定抛出该异常。
IllegalBlockingModeException
- 如果此套接字具有相关联的通道,且通道处于非阻塞模式。
DatagramPacket
,
SecurityManager.checkMulticast(InetAddress)
,
SecurityManager.checkConnect(java.lang.String, int)
public void receive(DatagramPacket p) throws IOException
DatagramPacket
的缓冲区填充了接收的数据。数据报包也包含发送方的 IP 地址和发送方机器上的端口号。
此方法在接收到数据报前一直阻塞。数据报包对象的 length
字段包含所接收信息的长度。如果信息比包的长度长,该信息将被截短。
如果存在安全管理器,而安全管理器的 checkAccept
方法不允许接收操作,则包不能被接收。
p
- 要放置传入数据的
DatagramPacket
。
IOException
- 如果发生 I/O 错误。
SocketTimeoutException
- 如果先前调用了 setSoTimeout 且超时值已过。
PortUnreachableException
- 套接字连接到当前不可达的目标时可能抛出。注意,不能保证一定抛出该异常。
IllegalBlockingModeException
- 如果此套接字具有相关联的通道,且通道处于非阻塞模式。
DatagramPacket
,
DatagramSocket
public InetAddress getLocalAddress()
如果存在安全管理器,则首先使用主机地址和 -1
作为参数调用其 checkConnect
方法,以查看是否允许该操作。
checkConnect
方法不允许该操作,则返回表示任何本地地址的
InetAddress
。
SecurityManager.checkConnect(java.lang.String, int)
public int getLocalPort()
public void setSoTimeout(int timeout) throws SocketException
timeout
- 指定的以毫秒为单位的超时值。
SocketException
- 如果底层协议出现错误,例如 UDP 错误。
getSoTimeout()
public int getSoTimeout() throws SocketException
SocketException
- 如果底层协议出现错误,例如 UDP 错误。
setSoTimeout(int)
public void setSendBufferSize(int size) throws SocketException
由于 SO_SNDBUF 是一种提示,想要验证缓冲区大小的应用程序应该调用 getSendBufferSize()
。
当发送率很高时,增大缓冲区的大小可以允许网络实现对多个传出包进行排队。
注:如果使用 send(DatagramPacket)
来发送比 SO_SNDBUF 设置大的 DatagramPacket
,包是被发送还是被丢弃是特定于实现的。
size
- 将设置的发送缓冲区大小。此值必须大于 0。
SocketException
- 如果底层协议出现错误,例如 UDP 错误。
IllegalArgumentException
- 如果值为 0 或负。
getSendBufferSize()
public int getSendBufferSize() throws SocketException
SocketException
- 如果底层协议出现错误,例如 UDP 错误。
setSendBufferSize(int)
public void setReceiveBufferSize(int size) throws SocketException
由于 SO_RCVBUF 是一种提示,想要验证缓冲区设置大小的应用程序应该调用 getReceiveBufferSize()
。
当包到达的速度快于使用 receive(DatagramPacket)
接收包的速度时,增大 SO_RCVBUF 可以允许网络实现缓存多个包。
注:是否能接收大于 SO_RCVBUF 的包是特定于实现的。
size
- 要设置的接收缓冲区大小。此值必须大于 0。
SocketException
- 如果底层协议出现错误,例如 UDP 错误。
IllegalArgumentException
- 如果值为 0 或负。
getReceiveBufferSize()
public int getReceiveBufferSize() throws SocketException
SocketException
- 如果底层协议出现错误,例如 UDP 错误。
setReceiveBufferSize(int)
public void setReuseAddress(boolean on) throws SocketException
对于 UDP 套接字可能有必要把超过一个的套接字绑定到相同的套接字地址。这样做的目的通常是为了接收多播包。(请参阅 MulticastSocket
)。如果在使用 bind(SocketAddress)
绑定套接字之前启用 SO_REUSEADDR 套接字选项,则 SO_REUSEADDR 套接字选项允许将多个套接字绑定到相同的套结字地址。
注意:所有现有平台都不支持此功能,因此不管是否将忽略此选项,它都是特定于实现的。但是,如果此功能不受支持,则 getReuseAddress()
将始终返回 false
。
当创建 DatagramSocket 时,禁用 SO_REUSEADDR 的初始设置。
在绑定套接字(请参阅 isBound()
)后启用或禁用 SO_REUSEADDR 时的行为是不确定的。
on
- 是否启用 SO_REUSEADDR 套接字选项
如果启用或禁用
-
SO_RESUEADDR 套接字选项时发生错误,或者关闭了套接字。
SocketException
getReuseAddress()
,
bind(SocketAddress)
,
isBound()
,
isClosed()
public boolean getReuseAddress() throws SocketException
boolean
值。
SocketException
- 如果底层协议出现错误,例如 UDP 错误。
setReuseAddress(boolean)
public void setBroadcast(boolean on) throws SocketException
on
- 是否开启广播。
SocketException
- 如果底层协议出现错误,例如 UDP 错误。
getBroadcast()
public boolean getBroadcast() throws SocketException
boolean
值。
SocketException
- 如果底层协议出现错误,例如 UDP 错误。
setBroadcast(boolean)
public void setTrafficClass(int tc) throws SocketException
tc 的值必须在 0 <= tc <= 255
范围内,否则将抛出 IllegalArgumentException。
注:
对于 Internet Protocol v4 该值由包含优先级和 TOS 字段的八位组组成,这在 RFC 1349 中有详细叙述。TOS 字段是由以下逐位或所得值创建的位集:
IPTOS_LOWCOST (0x02)
IPTOS_RELIABILITY (0x04)
IPTOS_THROUGHPUT (0x08)
IPTOS_LOWDELAY (0x10)
设置优先级字段中的位可能导致 SocketException,指示不允许该操作。
对于 Internet Protocol v6 tc
是将被放置到 IP 头部的 sin6_flowinfo 字段中的值。
tc
- 此位集的
int
值。
SocketException
- 如果设置流量类别或服务类型时出现错误
getTrafficClass()
public int getTrafficClass() throws SocketException
由于底层网络实现可能忽略使用 setTrafficClass(int)
设置的流量类别或服务类型,因而此方法可能返回一个不同于以前用 setTrafficClass(int)
在此 DatagramSocket 上设置的值。
SocketException
- 如果获得流量类别或服务类型值时出现错误。
setTrafficClass(int)
public void close()
在此套接字上 receive(java.net.DatagramPacket)
中所有当前阻塞的线程将会抛出 SocketException
。
如果此套接字有一个与之关联的通道,则关闭该通道。
public boolean isClosed()
public DatagramChannel getChannel()
DatagramChannel
对象(如果有)。
当且仅当通过 DatagramChannel.open
方法创建了通道本身时,数据报套接字才具有一个通道。
public static void setDatagramSocketImplFactory(DatagramSocketImplFactory fac) throws IOException
当应用程序创建新的数据报套接字时,调用套接字实现工厂的 createDatagramSocketImpl
方法创建实际的数据报套接字实现。
除非已经设置了工厂,否则向该方法传递 null
是无操作。
如果存在安全管理器,此方法首先调用安全管理器的 checkSetFactory
方法,确保允许该操作。这可能会导致 Sec