• 二. Socket用法


    C/S通信架构中,客户端要主动与服务端建立连接,这个链接就是Socket套接字.服务端收到连接请求后,也会开启Socket记录与客户端的链接.C/S两端都要建路Socket才能正常收发数据.

    一.构造Socket

    (1)new Socket ( )
    (2)new Socket ( InetAddress addres,int port )
    (3)new Socket ( String hostnamme,int port )
    以上3种创建socket的构造函数,除第一种外,都要试图简历与服务器的连接,连接成功返回Socket对象,连接失败,抛出IOException

    /** 扫描主机1-1024之间的端口,判断这些端口上是否有程序进行监听
    	 *  PortScanner与1-1024端口建立Socket对象,建立成功说明该端口上有程序进行监听
    	 */
    	public class PortScanner {
    		public static void main(String[] args) {
    			Socket socket = null;
    			for (int i = 1; i < 1024; i++) {
    				try {
    					socket = new Socket("localhost",i);
    					System.out.println(i+"端口有程序在监听");
    				} catch (IOException e) {
    					System.out.println(i+"端口空闲");
    				}finally {
    					try {
    						if(socket!=null)
    							socket.close();
    					} catch (IOException e) {
    						e.printStackTrace();
    					}   
    				}   
    			}   
    		}   
    	}
    

    二. 建立连接超时时间的Socket

        默认情况下,与服务端链接建立Socket时,会一直阻塞,直到服务端的操作系统返回信息表示连接建立,或抛出异常表示该端口无应用程序响应.受网络影响,Socket返回会有很长等待时间,因此可以设置建立连接产生Socket的阻塞时间(超时时间)

    Socket socket = new Socket();
    socket.connect(new InetSocketAddress("localhost",8080),60*1000); //一分钟超时时间
    

    三. Socket信息

    getInetASddress();     // 获取与之连接的服务端ip
    getPort();             // 获取与之连接的服务端port
    getLocalAddress();     
    getLocalPort();        // 客户端为该进程开启的端口
    

    四. Socket关闭

    当客户端与服务端通信结束,客户端应及时关闭Socket,释放为其开启的端口标识和其他资源

    finally {    // 释放操作放在finally块中
        try {
            if(socket!=null)
                socket.close();
        } catch (IOException e) {
            e.printStackTrace();
    }
    

    Socket可以只关闭输入流或者输出流

    shutdownInput();
    shutdownOutput();
    

    五. Socket选项

    **1. TCP_NODELAY **
        Socket连接发送数据默认采用Negale算法,即发送方发送的数据先缓存在底层缓冲区,当缓冲区满后,再将数据发送出去.这种方法减少了数据的传输次数来提高通信效率,适合发送大量数据,且接收方会及时相应的场景下.
        若发送方连续发送小批量数据,这些数据不会立刻发送而是会先缓存起来,导致实时响应速度很慢;例如客户端鼠标移动的信息需要实时发送到服务器上,采用Negale算法,会大大降低实时响应速度.
        关闭Negale发送算法 : setTcpNoDelay();
    **2. SO_RESUSEADDR: **
        socket的close()方法触发后,操作系统不会立刻释放该Socket所占端口,而是等一段时间,确保收到网络上发来的延迟数据,并不对该数据做任何处理.该段时间过后才释放端口.防止被其他恰巧绑定到相同端口的新进程收到该延迟数据.
        客户端来讲,操作系统为进程随机开启端口,一般不会使得新进程绑定到老进程的端口.对于服务端来说,进程挂掉后立即重启会重启失败,因为底层端口未被释放,而服务端进程应该响应客户端发来的延迟数据,所以服务端进程可以设置端口重用(setResuseAddress(true)).只有新老进程都设置了SO_RESUSEADDR,才能立刻端口重用

    //SO_RESUSEADDR要在Socket未绑定本地port钱调用,否则该选项设置无效,用如下方式开启socket链接
        public static void main(String[] args) throws IOException {
            Socket socket = new Socket();
            socket.setReuseAddress(true);
            socket.connect(new InetSocketAddress("localhost",8080),60*1000); //一分钟超时时间
        }
    

    3. SO_TIEMOUT

    byte[] buff = new byte[1024];
    InputStream in = socket.getInputStream();
    in.read(buff);
    

    若没有数据可读,则会一直阻塞,setTimeout(60*1000),设置读阻塞的超时时间为1分钟
    4. SO_LINGER
    Socket的close方法会立即返回,但底层端口未被立即释放,会延迟一段时间,等到所有数据发送,且接收到所有返回的确认包后,才真正关闭.socket的setSoLinger(true,3600),设置close()方法自多阻塞3600秒,若还有数据未被发送,则丢弃该部分数据
    5. SO_KEEPALIVE
    默认情况,Socket的KEEPALIVE选项为false,客户端发完消息,如果不手动调用close(),则socket会一直存在,不释放资源.setKeepAlive(true)后,当通信两端没有数据传输时,操作系统发现该socket已超过2小时空闲,则会自动发送一个测试包给远程机器,测试包会持续尝试11分钟,若在12分钟内没收到远程机器发来的确认包,操作系统则会自动关闭本地Socket,释放资源
    **6. OOBINLINE **
    当setOOBLine(true),操作系统支持发送紧急数据,sendUrgent(int data)发送一个字节的紧急数据.默认情况OOBINLINE为false.但是接收方仍会把改紧急数据放到普通数据的队列中,紧急数据到来,接收方不会得到任何通知,所以接收方无法区分普通数据和紧急数据,只能按照相同方式处理

  • 相关阅读:
    Mysql(11)_Mysql权限与安全
    Mysql(10)_存储过程与流程控制
    Java(43)_AWT事件处理挂关闭生效
    6.实现合同测试用例
    6.测试库优化
    5.案例回顾及编写测试用例
    4.测试案例实现代码库与测试用例V2.0
    3.测试案例实现代码库与测试用例
    markdown语法学习
    1.faker批量随机造数据
  • 原文地址:https://www.cnblogs.com/72808ljup/p/5290085.html
Copyright © 2020-2023  润新知