Socket
基本操作
Socket是两台主机之间的一个连接。它可以完成7个基本操作
- 连接远程机器
- 发送数据
- 接收数据
- 关闭连接
- 绑定端口
- 监听入站数据
- 在绑定端口上接收来自远程机器的连接
Java的Socket类提供了对应前4个操作的方法,后三个仅服务器需要,即等待客户端的连接
构造
- Socket(InetAddress address, int port)
创建一个流套接字并将其连接到指定 IP 地址的指定端口号。 - Socket(String host, int port)
创建一个流套接字并将其连接到指定主机上的指定端口号。 - Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
创建一个套接字并将其连接到指定远程地址上的指定远程端口。 - Socket(String host, int port, InetAddress localAddr, int localPort)
创建一个套接字并将其连接到指定远程主机上的指定远程端口。
以上四种方法在创建对象时都会连接socket
如果localPort参数传入0,Java会随机选择1024到65535之间的一个可用端口
- Socket()
通过系统默认类型的 SocketImpl 创建未连接套接字 - Socket(Proxy proxy)
创建一个未连接的套接字并指定代理类型(如果有),该代理不管其他设置如何都应被使用。
获取Socket的信息
- public InetAddress getInetAddress()
返回套接字连接的地址。 - public int getPort()
返回此套接字连接到的远程端口 - public InetAddress getLocalAddress()
获取套接字绑定的本地地址 - public int getLocalPort()
返回此套接字绑定到的本地端口 - public InputStream getInputStream()
返回此套接字的输入流。 - public OutputStream getOutputStream()
返回此套接字的输出流。
连接
- public void connect(SocketAddress endpoint)
- public void connect(SocketAddress endpoint,int timeout)
当创建未连接套接字后,使用此方法将此套接字连接到服务器
参数:
endpoint - SocketAddress
timeout - 要使用的超时值(以毫秒为单位)。
关闭
- public void close()
关闭此套接字。 - public void shutdownInput()
关闭输入流,关闭输入之后再读取输入流会返回-1 - public void shutdownOutput()
关闭输出流,关闭输出之后再写入Socket则会抛出一个IOException异常
状态
- public boolean isInputShutdown()
返回是否关闭套接字连接的半读状态。如果已关闭套接字的输入,则返回 true - public boolean isOutputShutdown()
返回是否关闭套接字连接的半写状态。如果已关闭套接字的输出,则返回 true - public boolean isClosed()
如果socket关闭,isClosed()方法会返回ture,否则返回false,如果Socket从一开始从未连接,isClosed()也返回false - public boolean isConnected()
Socket是否从未连接过一个远程主机 - public boolan isBound()
Socket是否成功地绑定到本地系统上的出站端口
设置Socket选择
- TCP_NODELAY
设置TCP_NODELAY为ture可确保包会尽可能块的发送,而无论包的大小。即关闭了Socket的缓冲
使用public boolean getTcpNoDelay()查询
使用public void setTcpNoDelay(boolean on)修改 - SO_TIMEOUT
正常情况下,尝试从Socket读取数据时,read()调用会阻塞尽可能长的时间来得到足够的字节。设置SO_TIMEOUT可以确保这次调用组设的时间不会超过某个固定的毫秒数。0被解释为无限超时,这是默认值
使用public int getSoTimeout()查询
使用public void setSoTimeout(int timeout)修改,timeout以毫秒为单位 - SO_LINGER
SO_LINGER选项指定了Socket关闭时如何处理尚未发送的数据报。
默认情况下,close()方法将立即返回,但系统仍会尝试发送剩余的数据。
如果延迟时间设置为0,那么当Socket关闭时,所有未发送的数据包都将被丢弃。
如果SO_LINGER打开而且延迟时间设置为正数,close()方法会阻塞(阻塞时间为指定的秒数),等待发送数据和接收确认,当过去相应秒数后,Socket关闭,所有剩余的数据都不会发送,也不会收到确认
使用public int getSoLinger()查询,当返回-1时表示该项被禁用
使用public void setSoLinger(boolean on, int linger)修改,linger以秒为单位 - SO_SNDBUF
SO_SNDBUF选项控制用于网络输入的建议的发送缓冲区大小
使用public int getSendBufferSize()查询
使用public void setSendBufferSize(int size)修改 - SO_RCVBUF
SO_RCVBUF选项控制用于网络输入的建议的接收缓冲区大小
使用public int getReceiveBufferSize()查询
使用public void setReceiveBufferSize(int size)修改 - SO_KEEPALIVE
如果打开了SO_KEEPALIVE,客户端会通过一个空闲连接发送一个数据包(一般两小时一次),以确保服务器未崩溃。如果服务器没有响应这个包,客户端会持续尝试11分钟多的时间,直到接收到响应为止。如果在12分钟内未收到响应,客户端就关闭socket。如果没有SO_KEEPALIVE,不活动的客户端可能会永久存在下去,而不会注意到服务器已经崩溃
使用public boolean getKeepAlive()查询
使用public void setKeepAlive(boolean on)修改 - OOBINLINE
默认情况下,此选项是禁用的。如果希望接收正常数据中的紧急数据,就需要设置此项为true
使用public boolean getOOBInline()查询
使用public void setOOBInline(boolean on)修改 - SO_REUSEADDR
当一个Socket关闭时,可能不会立即释放本地端口,这将会阻止所有其他Socket绑定到一个已知端口,如果开启SO_REUSEADDR(默认为关闭),就允许另一个Socket绑定到这个端口
使用public boolean getReuseAddress()查询
使用public void setReuseAddress(boolean on)修改
要正常使用这些方法,setReuseAddress()必须在为这个端口绑定新Socket之前调用。这以为着Socket必须使用无参数构造函数以非连接状态创建,然后调用setReuseAddress(ture),再使用connect()方法连接Socket。之前连接的Socket和重用老地址的新Socket都必须设置SO_REUSEADDR为ture,这样才能生效 - IP_TOS
使用public int getTrafficClass()查询
使用public void setTrafficClass(int tc)修改
tc的值为0到255之间,这个字节的高六位包含一个差分服务代码点(DSCP)值,低两位包含一个显式拥塞通知(ECN)值
常用DSCP值和解释
PHB(逐跳行为) | 二进制值 | 用途 |
---|---|---|
默认 | 00000 | Best-effort(尽力)业务流 |
加速转发 | 101110 | 低损耗,低延迟,低抖动业务流,通常仅限于网络容量的30%或更低 |
保证转发 | 多个 | 保证最多以一个指定速率传送 |
类选择器 | xxx000 | 与IPv4 TOS首部向后兼容 |
保证转发优先级分类
第一类(最低优先级) | 第二类 | 第三类 | 第四类(最高优先级) | |
---|---|---|---|---|
低丢包率 | AF11(001010) | AF21(010010) | AF31(011010) | AF41(100010) |
中丢包率 | AF12(001100) | AF22(010100) | AF32(011100) | AF42(100100) |
高丢包率 | AF13(001110) | AF23(010110) | AF33(011110) | AF43(100110) |
public void setPerformancePreferences(int connectionTime,int latency,int bandwidth)
设置此套接字的性能偏好。 此方法在连接套接字后调用此方法无效。
参数:
connectionTime - 表达短连接时间的相对重要性的 int
latency - 表达低延迟的相对重要性的 int
bandwidth - 表达高带宽的相对重要性的 int