tcp 和 java socket
?
tcp socket 总结点
?
1、操作系统分为内核态和用户态,tcp协议实现属于操作系统内核态,然后socket传输过程中发送方和接收方都有自己的窗口(buffer),那么就必须会有内核态的buffer到用户态的buffer拷贝
?
2、java 的socket只是通过java本地方法调用基于操作系统的tcp实现
?
3、 tcp不同与udp,udp只是尽自己努力的把数据传送到目的地,但tcp是必须保证数据传送过去,在传送过程中会使用发送和确认,重试的方式来保证数据的传达
?
4、数据传输开始使用发一个数据,等待一个确认,后来发现这样太慢,就使用一次发送多个数据,等待多个数据的确认,如果没有收到确认,或者在确认中发现遗漏了一个数据,会发起重试。
?
5,发送方和接收方都有自己的窗口(buffer),这个窗口时可变的,在java中可以通过sendbuffersize和recivebuffersize来设置,发送方的可用窗口大小为 buffersize - (等待发送数据+等待确认数据) ? 接收方的可用窗口大为buffersize-(按序到达,等待用户读取+未按时到达,等待重新发送) 如果接收方的窗口慢了,那么会告诉发送发,那么发送方将暂时不会发送给接收方,用户发送数据先写到发送缓冲,如果发送缓冲已满,将会阻塞。
?
6、在内核态中,如果发送窗口已满,将阻塞write,如果接受窗口为空,将会阻塞read
?
7,Nagle算法,主要是为了节省流量的目的,当用户逐个字节的发送数据时,会把字节缓冲起来,组成一个报文发送。
?
8,在使用netty或mina是要注意,如果发送缓冲区已满,那么将会阻塞发送,netty或mina将会把发送的请求保存在内存中,如果保存的过多可能会发生outofmemory错误。
?
linux IO模型
阻塞,同步IO:比如读,如果窗口没有数据,将一直等待,比如listen,如果没有新的连接,将一直等待 ? java IO使用该方式
?
非阻塞,同步IO:比如读,如果窗口没有数据,将返回false,使用轮询模式
?
IO复用,阻塞(半阻塞),同步IO:IO复用主要是把read或linsten或connect或write等操作注册到系统中,使用轮询方式判断是否有事件发生,然后触发事件 ? ?java NIO使用该方式
?
信号驱动,非阻塞,同步:将兴趣注册到系统中,此时不需要轮询,当有事件发生时,将递交信号
?
非阻塞,异步IO:从概念上说,应该用户会提供一个回调方法,内核把数据直接把数据拷贝给用户,填充用户提供的缓冲区,完后通知用户,这种方式看上去很完美,可惜目前java不支持这种方式。
?
?
?
TCP的几种状态
LISTEN:侦听来自远方的TCP端口的连接请求
SYN-SENT:再发送连接请求后等待匹配的连接请求
SYN-RECEIVED:再收到和发送一个连接请求后等待对方对连接请求的确认
ESTABLISHED:代表一个打开的连接
FIN-WAIT-1:等待远程TCP连接中断请求,或先前的连接中断请求的确认
FIN-WAIT-2:从远程TCP等待连接中断请求
CLOSE-WAIT:等待从本地用户发来的连接中断请求
CLOSING:等待远程TCP对连接中断的确认
LAST-ACK:等待原来的发向远程TCP的连接中断请求的确认
TIME-WAIT:等待足够的时间以确保远程TCP接收到连接中断请求的确认
CLOSED:没有任何连接状态