网络编程中的Socket详解---Socket重要参数详解

Java Socket的api可能不少人会用,可是Java Socket的参数可能不少人都不知道用来干吗的,甚至都不知道有这些参数。java


backlog

用于ServerSocket,配置ServerSocket的最大客户端等待队列。等待队列的意思,先看下面代码算法

public class Main {
    public static void main(String[] args) throws Exception {
        int port = 8999;
        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 8999测试下。
这个参数设置为-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,除非咱们禁用纳格算法,数据就会当即发送了。
另外有一篇讲解纳格算法和delay ack的文章(挺不错的):http://blog.csdn.net/frankggyy/article/details/6624401  

SoLinger
当咱们调用socket.close()返回时,socket已经write的数据未必已经发送到对方了,例如


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,如:
bool 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参数了,其余就不另外说明了。

版权声明:本文为博主原创文章,未经博主容许不得转载。api

相关文章
相关标签/搜索