Socket问题小结

1.    Socket(TCP/IP)通讯,需要两端的Socket都持有连接,当Client端去远端connect时(成功之前),首先会bind到本地的一个可用的端口(可以通过socket.bind(InetAddress)来手动指定),可以通过socket.boud()检测是否已经bind成功.

尽管Socket Client端建立连接时bind的端口通常我们不关心,但是这是TCP建立连接的条件.即每个Client建立一次连接,都会导致本地一个端口被"暂时"占用,直到Socket关闭,由此可见Client申请链接的个数也是有极限的.(客户端可以建立的连接数是有限的,65535)

可以通过socket.getPort()获取此socket维持的远端端口,socket.getLocalPort()获取当前socket本地bind的端口;对于serverSocket.accept()获取到的socket,那么其LocalPort即为serverSocket.bind指定的端口.

TCP连接的建立,需要对等端都能有效的维护Socket,双端都明确通讯的port是必须的.Server端需要知道client端的port,因为其需要向client端write数据.

 

参考:http://www.cnblogs.com/doctorqbw/archive/2011/12/13/2286063.html

 

Socket socket = new Socket();
socket.setSoTimeout(20000);
//socket.setTcpNoDelay(true);
socket.connect(new InetSocketAddress(port));//bind本地端口
if (!socket.isConnected()) {
System.out.println("Connect error!");
}
//获知socket的终端的port.
System.out.println("Connected:!RemotePort:" + socket.getPort() + "//LocalPort:" + socket.getLocalPort());
ServerSocket socket = new ServerSocket();
try{
	//socket.setSoTimeout(20000);
    socket.setReuseAddress(true);
    socket.bind(new InetSocketAddress(port));
    Socket accept = null;
    while ((accept = socket.accept()) != null) {
        accept.setTcpNoDelay(true);
		//客户端连接接收成功,那么此时Socket可以获取client端的端口,以及本机bind的端口
        System.out.println("Connected Server!RemotePort:" + accept.getPort() + "//LocalPort:" + accept.getLocalPort());
}
}catch (Exception e) {
    e.printStackTrace();
}finally{
	socket.close();
}

 

 

标记一个socket的通讯,通过组合"remote address" + "remote port" + "local port" + "local address"来唯一标记一个TCP连接,因此server端只需要一个端口,可以接受大量的链接请求(上诉四个组合中,对于server端socket而言,remote address + remote port组合的数量具有不确定性).但是对于客户端一个socket只能和一个server中断连接(上述四个组合值都是确定性的.),client端一个port只能维持一个连接.并非请求可以无限增长,因为每个链接就意味着一个IO文件描述符被打开.Server端的端口,即时serverSocket侦听连接的端口,也是数据传输的端口.

 

2.   理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭 连接之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”(过程就不细写了,就是服务器和客 户端交互,最终确定断开) 

 

3.    Socket中对TPC选项KEEP_ALIVE的设置,keepAlive经常用户连接需要被"维护为"长连接方式.TCP-socket两端都可以设置此值,其中设置为true的一端(或2端)负责维护连接的存活性.KeepAlive参数在高并发高/吞吐量/连接周期较短的应用中,应该被关闭,否则会因为其他原因导致socket没有关闭的情况下,仍然在消耗系统资源.在Socket上长时间没有write操作(以及read)时,socket将意识不到远端的连接是否还有效,如果此时调用write,将会发现连接已经被关闭.为了避免这种事情,KeepAlive为true的一端,keepAlive就是在一短时间空闲后,有一端主动发送"探测"数据包,如果数据包被接收,则表示连接仍然存活(且维持为存活),否则多次探测仍没有得到回应,此时socket将被异常关闭.

KeepAlive一旦开启,维持活性的一端,此socket将不会被轻易销毁,直到远端关闭位置.所以keepAlive对于维护端是一种性能上的开支.(长期占用资源,以及探测)

 

Socket两端只要有一端Close,那么另一端尝试去write将会抛出"connection error",尝试去read将会被无限阻塞.因为任何一端socket.close,都将导致底层TCP连接断开.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值