package commonsNet
import std.net.UdpSocket
import std.net.IPSocketAddress
public abstract class DatagramSocketClient {
//所有 DatagramSocketClient 实例共享的默认 DatagramSocketFactory
private static let DEFAULT_SOCKET_FACTORY: DefaultDatagramSocketFactory = DefaultDatagramSocketFactory.DEFAULT;
/** 默认超时 */
protected var _timeout_: Int64
/** 用于连接的数据报套接字 */
protected var _socket_: ?UdpSocket
/** 客户端的套接字当前是否处于打开状态 */
protected var _isOpen_: Bool
/** 数据报套接字的 DatagramSocketFactory */
protected var _socketFactory_: DatagramSocketFactory
/**
* 无参构造函数
* _socket_=None;
* _timeout_=0;
* _isOpen_=false;
* _socketFactory_= DEFAULT_SOCKET_FACTORY;
*/
public init() {
this._socket_ = None
this._timeout_ = 0
this._isOpen_ = false
this._socketFactory_ = DEFAULT_SOCKET_FACTORY
}
/** 属性readTimeout,用于设置和获取readTimeout */
public mut prop receiveTimeout: ?Duration {
get() {
this._socket_.getOrThrow().receiveTimeout
}
set(value) {
this._socket_.getOrThrow().receiveTimeout = value
}
}
/** 属性sendTimeout,用于设置和获取sendTimeout */
public mut prop sendTimeout: ?Duration {
get() {
this._socket_.getOrThrow().sendTimeout
}
set(value) {
this._socket_.getOrThrow().sendTimeout = value
}
}
/**
* 得到非空的UdpSocket或者抛出异常
*/
protected func checkOpen(): UdpSocket {
return this._socket_.getOrThrow {NoneValueException("DatagramSocket is None.")}
}
/**
* 用于关闭套接字
*
* 应该在类实例使用完后以及再次调用{@link #open open() } 之前调用此方法
* _isOpen_ 设置为false
* _socket_ 设置为none
*/
public func close() {
if (let Some(s) <- this._socket_) {
s.close();
}
this._socket_ = None
this._isOpen_ = false
}
/**
* 获取打开套接字时使用的默认超时(以毫秒为单位)
*/
public func getDefaultTimeout(): Int64 {
return this._timeout_;
}
/**
* 获取客户端的套接字绑定到的本地地址。
*
* 如果在客户端套接字未打开时调用此方法抛出异常
*/
public func getLocalAddress(): Array<UInt8> {
if (this.isOpen()) {
return checkOpen().localAddress.getAddressBytes();
} else {
throw NoneValueException("UdpSocket is not open")
}
}
/**
* 获取本地主机上打开的用于连接的套接字的端口号。
*
* 如果在客户端套接字未打开时调用此方法,则抛出异常
*/
public func getLocalPort(): UInt16 {
if (this.isOpen()) {
return IPSocketAddress.parse(checkOpen().localAddress.toString()).port
} else {
throw NoneValueException("UdpSocket is not open")
}
}
/**
* 如果客户端具有当前打开的套接字,则为 true。
*/
public func isOpen(): Bool {
return this._isOpen_;
}
/**
* 在本地主机上的第一个可用端口处打开 DatagramSocket。
*
* _socket_ 设置为新打开的套接字,Udpsocket需要调用bind()绑定
* _isOpen_ 设置为 true,receiveTimeout和sendTimeout设置为默认超时
*/
public func open() {
this._socket_ = this._socketFactory_.createDatagramSocket()
this._socket_.getOrThrow().bind();
this.receiveTimeout = Duration.millisecond * this._timeout_
this.sendTimeout = Duration.millisecond * this._timeout_
_isOpen_ = true
}
/**
* 在本地主机上的指定端口处打开 DatagramSocket
*
* _socket_ 设置为新打开的套接字,Udpsocket需要调用bind()绑定
* _isOpen_ 设置为 true,receiveTimeout和sendTimeout设置为默认超时
*/
public func open(port: UInt16) {
this._socket_ = _socketFactory_.createDatagramSocket(port)
this._socket_.getOrThrow().bind();
this.receiveTimeout = Duration.millisecond * this._timeout_
this.sendTimeout = Duration.millisecond * this._timeout_
_isOpen_ = true
}
/**
* 在指定端口的本地主机上的指定地址处打开 DatagramSocket
*
* _socket_ 设置为新打开的套接字,Udpsocket需要调用bind()绑定
* _isOpen_ 设置为 true,receiveTimeout和sendTimeout设置为默认超时
*/
public func open(IPSocketAddress: IPSocketAddress) {
this._socket_ = _socketFactory_.createDatagramSocket(IPSocketAddress: IPSocketAddress)
this._socket_.getOrThrow().bind();
this.receiveTimeout = Duration.millisecond * this._timeout_
this.sendTimeout = Duration.millisecond * this._timeout_
_isOpen_ = true
}
/**
* 设置DatagramSocketClient使用的DatagramSocketFactory来打开DatagramSockets
*
* 如果DatagramSocketFactory为none,则使用默认的DatagramSocketFactory
*/
public func setDatagramSocketFactory(factory: ?DatagramSocketFactory) {
_socketFactory_ = factory ?? DEFAULT_SOCKET_FACTORY
}
/**
* 设置打开套接字时使用的默认超时
*
* 此方法应在调用 {@link #open open()} 之前使用
*/
public func setDefaultTimeout(timeout: Duration) {
_timeout_ = timeout.toMilliseconds()
}
/**
* 设置打开套接字时使用的默认超时
*
* 此方法应在调用 {@link #open open()} 之前使用
*/
public func setDefaultTimeout(timeout: Int64) {
_timeout_ = timeout
}
}