美文网首页
socket常用属性设置

socket常用属性设置

作者: jerrik | 来源:发表于2017-10-10 11:05 被阅读0次

    Java Socket的api可能很多人会用,但是Java Socket的参数可能很多人都不知道用来干嘛的,甚至都不知道有这些参数。

    Backlog

    public class Main {
        public static void main(String[] args) throws Exception {
            int port = 9999;
            int backlog = 2;
            ServerSocket serverSocket = new ServerSocket(port, backlog);
            Socket clientSock = serverSocket.accept();
            System.out.println("revcive from " + clientSock.getPort());
            while (true) {
                byte buf[] = new byte[1024];
                int len = clientSock.getInputStream().read(buf);
                System.out.println(new String(buf, 0, len));
            }
        }
    }
    

    这段测试代码在第一次处理一个客户端时,就不会处理第二个客户端,所以除了第一个客户端,其他客户端就是等待队列了。所以这个服务器最多可以同时连接3个客户端,其中2个等待队列。大家可以telnet localhost 9999测试下。
    这个参数设置为-1表示无限制,默认是50个最大等待队列,如果设置无限制,那么你要小心了,如果你服务器无法处理那么多连接,那么当很多客户端连到你的服务器时,每一个TCP连接都会占用服务器的内存,最后会让服务器崩溃的。
    另外,就算你设置了backlog为10,如果你的代码中是一直Socket clientSock = serverSocket.accept(),假设我们的机器最多可以同时处理100个请求,总共有100个线程在运行,然后你把在100个线程的线程池处理clientSock,不能处理的clientSock就排队,最后clientSock越来越多,也意味着TCP连接越来越多,也意味着我们的服务器的内存使用越来越高(客户端连接进程,肯定会发送数据过来,数据会保存到服务器端的TCP接收缓存区),最后服务器就宕机了。所以如果你不能处理那么多请求,请不要循环无限制地调用serverSocket.accept(),否则backlog也无法生效。如果真的请求过多,只会让你的服务器宕机(相信很多人都是这么写,要注意点)

    TcpNoDelay

    禁用纳格算法,将数据立即发送出去。纳格算法是以减少封包传送量来增进TCP/IP网络的效能,当我们调用下面代码,如:

    Socket socket = new Socket();  
    socket.connect(new InetSocketAddress(host, 8000));  
    InputStream in = socket.getInputStream();  
    OutputStream out = socket.getOutputStream();  
    String head = "hello ";  
    String body = "world\r\n";  
    out.write(head.getBytes());  
    out.write(body.getBytes());
    

    我们发送了hello,当hello没有收到ack确认(TCP是可靠连接,发送的每一个数据都要收到对方的一个ack确认,否则就要重发)的时候,根据纳格算法,world不会立马发送,会等待,要么等到ack确认(最多等100ms对方会发过来的),要么等到TCP缓冲区内容>=MSS,很明显这里没有机会,我们写了world后再也没有写数据了,所以只能等到hello的ack我们才会发送world,除非我们禁用纳格算法,数据就会立即发送了。应用场景一般在对网络延时要求非常高的情况下使用(或者弱网情况下)

    SoLinger

    Socket socket = new Socket();  
    socket.connect(new InetSocketAddress(host, 8000));  
    InputStream in = socket.getInputStream();  
    OutputStream out = socket.getOutputStream();  
    String head = "hello ";  
    String body = "world\r\n";  
    out.write(head.getBytes());  
    out.write(body.getBytes()); 
    socket.close();
    

    这里调用了socket.close()返回时,hello和world未必已经成功发送到对方了,如果我们设置了linger而不小于0,如:

    boolean on = true;
    int linger = 100;
    socket.setSoLinger(boolean on, int linger);
    socket.close();
    

    那么close会等到发送的数据已经确认了才返回。但是如果对方宕机,超时,那么会根据linger设定的时间返回。

    UrgentData和OOBInline

    TCP的紧急指针,一般都不建议使用,而且不同的TCP/IP实现,也不同,一般说如果你有紧急数据宁愿再建立一个新的TCP/IP连接发送数据,让对方紧急处理。
    所以这两个参数,你们可以忽略吧,想知道更多的,自己查下资料。
    SoTimeout
    设置socket调用InputStream读数据的超时时间,以毫秒为单位,如果超过这个时候,会抛出java.net.SocketTimeoutException。

    KeepAlive

    keepalive不是说TCP的常连接,当我们作为服务端,一个客户端连接上来,如果设置了keeplive为true,当对方没有发送任何数据过来,超过一个时间(看系统内核参数配置),那么我们这边会发送一个ack探测包发到对方,探测双方的TCP/IP连接是否有效(对方可能断点,断网),在Linux好像这个时间是75秒。如果不设置,那么客户端宕机时,服务器永远也不知道客户端宕机了,仍然保存这个失效的连接。

    SendBufferSize和ReceiveBufferSize

    TCP发送缓存区和接收缓存区,默认是8192,一般情况下足够了,而且就算你增加了发送缓存区,对方没有增加它对应的接收缓冲,那么在TCP三握手时,最后确定的最大发送窗口还是双方最小的那个缓冲区,就算你无视,发了更多的数据,那么多出来的数据也会被丢弃。除非双方都协商好。

    以上的参数都是比较重要的Java Socket参数了,其他就不另外说明了。

    相关文章

      网友评论

          本文标题:socket常用属性设置

          本文链接:https://www.haomeiwen.com/subject/ybhvyxtx.html