Socket

Author Avatar
罗炜光 5月 11, 2016
  • 在其它设备中阅读本文章

基本操作

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