(2)详解Socket类

xiaoxiao2021-02-28  111

Socket建立在TCP/IP协议的基础上,可以看做是通信连接两端的收发器,是两台机器间通信的端点,服务器与客户端都通过Socket来收发数据。 本文从构造器,异常,方法三个方面来详解Socket类 一、构造方法 Socket有以下几种常用的构造方法: (1)Socket() (2)Socket(InetAddress address, int port) (3)Socket(String host, int port) (4)Socket(InetAddress address, int port, InetAddress localAddr, int localPort) (5)Socket(String host, int port, InetAddress localAddr, int localPort) 先说一下构造方法中的参数InetAddress类,该类表示IP地址,它提供了一系列静态工厂方法。列如: InetAddress address1 = InetAddress.getLocalHost(); //获取本地主机IP InetAddress address1 = InetAddress.getByName("192.168.2.36"); //返回 192.168.2.36的IP InetAddress address1 = InetAddress.getByName("www.baidu.com"); //返回www.baidu.com的IP 除3第一种构造方法外,其他几种都会在初始化时试图建立与服务器的连接,如果成功,返回Socket对象,如果因为某些原因失败,会抛出IOException。 当Socket请求与服务器连接时,可能要等待一段时间,默认情况下,会一直等下去,直到成功或者抛出异常。例如底层网络传输速度很慢,可能就会等待很久,这个时候通常会限定等待时间,此时就需要使用第一个不带参数的构造器: Socket socket = new Socket(); SocketAddress address = new InetSocketAddress("localhost",8000); Socket.connect(address,60000); //设置等待时间为6万毫秒,即1分钟 用这种方法创建Socket如果限定时间内连接成功,connect顺利返回,如果不成功,抛出SocketTImeoutException 这里的connect(SocketAddress endpoint, int timeout )方法作用是将此套接字连接到服务器,并指定一个超时值。 对于其他的构造方法,都需要早参数中设置服务器地址,包括IP地址或主机名,以及端口。再一个Socket对象中,既包含服务器IP和端口,又包含客户端IP和端口,默认情况下,客户端IP为客户端所在主机IP,端口由操作系统随机分配。而一台主机如果处于多个网络中(如同时处于Internet和局域网),就会有多个IP,当我们想要客户端使用某个IP时,就可以使用第(4)(5)中构造方法指定客户端的IP和端口。 二、异常 Socket的构造方法连接主机时,可能会抛出以下几种异常: UnknownHostException:无法识别主机名字或IP ConnectException:没有服务器监听指定端口,或服务器拒绝连接 SocketTimeoutException:连接超时 BindException:无法把Socket对象与指定本地IP或端口绑定 三、方法 以下为Socket类提供的常用方法,在这里我分为三类: 1.从Socket中获取信息的方法: getInetAddress();    //返回套接字连接的地址。 返回类型为InetAddress getInputStream();    // 返回此套接字的输入流。 返回类型为InputStream getLocalAddress();   //获取套接字绑定的本地地址。 返回类型为InetAddress getLocalPort();   //返回此套接字绑定到的本地端口。 返回类型为int getLocalSocketAddress();   // 返回此套接字绑定的端点的地址,如果尚未绑定则返回 null。 返回类型为SocketAddress getOutputStream();   //返回此套接字的输出流。 返回类型为OutputStream getPort();   //返回此套接字连接到的远程端口。 返回类型为int getRemoteSocketAddress();   // 返回此套接字连接的端点的地址,如果未连接则返回 null。 返回类型为SocketAddress 2.关闭Socket的相关方法: 当客户端与服务器结束通信后,应及时关闭Socket,以释放Socket占用的各种资源 close()方法用于关闭Socket对象,当一个对象被关闭后,将不能进行I/O操作,所以close()方法通常写在finally块中,否则会导致IOException。 Socket为测试Socket的状态提供了三种方法 isBound()   // 返回套接字的绑定状态。 isClosed()   //返回套接字的关闭状态。 isConnected()   //返回套接字的连接状态。 如果判断一个Socket是否处于连接状态,可以用以下的方法: boolean flag = socket.isConnected() && !socket.isClosed(); 当调用close()方法时,输入流和输出流都被关闭,而有时只需要关闭其中一个,此时采用Socket提供的半关闭方法: shutdownInput()   //关闭输入流 shutdownOutput()   //关闭输出流 这里需要注意,关闭了输入输出流不等于关闭了Socket,所以最后还是需要执行close()方法 测试半关闭的方法: isInputShutdown() isOutputShutdown() 3.设置Socket属性的相关方法: Socket有以下几种属性: (1)TCP_NODELAY:表示立即发送数据报 setTcpNoDelay(boolean on)    //启用/禁用 TCP_NODELAY(启用/禁用 Nagle 算法)。 采用Nagle 算法不会立即发送数据,会将数据放在缓冲区中,缓冲区满了再发送,默认为false,表示采用Nagle 算法 (2)SO_RESUSEADD:表示是否允许重用Socket所绑定的本地地址 setReuseAddress(boolean on) 关闭Socket后,不会立即释放端口,会等一段时间来接收延迟数据,这样确保延迟数据不会被关闭后新绑定到此端口的Socket收到。 setReuseAddress(boolean on)设置为true,关闭Socket后,此端口可立即被重用。 这里需要注意,该方法必须在Socket绑定端口前调用,否则无效。可以用以下的创建方式: Socket socket = new Socket(); socket.setReuseAddress(true); socket.connect(new SocketAddress("remotehost",8000)); (3)SO_TIMEOUT:表示接受数据报的等待超时时间。 setSoTimeout(int timeout)  //启用/禁用带有指定超时值的 SO_TIMEOUT,以毫秒为单位。默认为0,表示不会超时,会一直等待下去 (4)SO_LINGER:当执行close()方法时,是否立即关闭底层Socket setSoLinger(boolean on, int linger)  // 启用/禁用具有指定逗留时间(以秒为单位)的 SO_LINGER。 默认情况下,执行Socket的close()方法,会立即返回,但是底层的Socket对象并不会立刻关闭 如果执行以下方法: socket.setSoLinger(true,0); socket.close(); close()会立即返回,底层的Socket对象也会立刻关闭,未发送完的数据直接关闭; 如果执行以下方法: socket.setSoLinger(true,100); socket.close(); close()方法不会立即返回,而是进入阻塞状态,在100秒内发送完数据时返回,或到达100秒没发送完数据,也返回,剩余数据丢弃 (5)SO_SNFBUF:发送数据缓冲区大小 setSendBufferSize(int size)   // 将此 Socket 的 SO_SNDBUF 选项设置为指定的值 用于设置输入缓冲区的大小,一般传输大的文件,如HTTP,FTP协议的通信,都采用较大的缓冲区,可以减少传输数据的次数,对于次数频繁而数据量比较小的数据,如网络游戏,通常采用比较小的缓冲区,确保能快速收发数据 (6)SO_RCVBUF:接受数据缓冲区大小 setReceiveBufferSize(int size)   //将此 Socket 的 SO_RCVBUF 选项设置为指定的值。 缓冲区的设置规则和SO_SNFBUF选项相同 (7)SO_KEEPALIVE:长期处于空闲状态的Socket,是否自动关闭 setKeepAlive(boolean on)    //启用/禁用 SO_KEEPALIVE。 把该方法设置为true,空闲连接(连接两端没有收发数据)超过2小时,会自动关闭,该选项的默认值为false,不会监听空闲连接,不活动的客户端会永久存活,直到服务器崩溃。 (8)OOBINLINF:是否支持发送一个字节的紧急数据报 setOOBInline(boolean on)   //启用/禁用 OOBINLINE(TCP 紧急数据的接收者) 默认情况下,此选项是禁用的,即在套接字上接收的 TCP 紧急数据被静默丢弃。 将此方法设置为true,则可以调用以下方法发送紧急TCP数据报: socket.sendUrgentData(int data);    //  在套接字上发送一个紧急数据字节。 除非使用一些高层次协议,否则接收方很难区分普通数据报和紧急数据报,只能按照同样的方式处理它们 获取这些属性值得get方法在这里省略。
转载请注明原文地址: https://www.6miu.com/read-25367.html

最新回复(0)