Java网络编程入门

 Java网络编程入门

服务器与客户程序只需关心发送什么样的数据给对方,而不必考虑如何把这些数据传输给对方,传输数据的任务由计算机网络完成。

两个进程顺利通信的前提条件是它们所在的主机都连接到了计算机网络上。

网络协议是网络中主机之间通信的语言。

不同网络之间的互联靠网络上的标准语言——TCP/IP协议。

OSI参考模型把网络分为7层,分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。不同主机之间的相同层称为对等层。

物理层:为上一层提供物理连接,以及规定通信节点之间的机械和电气特性。数据作为原始的比特(bit)流传输。

数据链路层:数据链路层负责在两个相邻节点间的线路上,无差错地传送以帧为单位的数据。典型设备是交换机。

网络层:选择合适的网间路由和交换节点,确保数据及时传送到目标主机。典型设备是路由器。

传输层:根据通信子网的特性最佳地利用网络资源,为两个端系统的会话层提供建立、维护和取消传输连接的功能,以可靠方式或不可靠方式传输数据。信息的传送单位是报文。

会话层:管理进程间的会话过程,即负责建立、管理、终止进程间的会话。数据传送单位是报文。

表示层:对上层数据进行转换,以保证一个主机的应用层的数据可以被另一个主机的应用层理解。数据传送单位是报文。

应用层:确定进程间通信的实际用途,以满足用户实际需求。

发送方每一层会给上一层传递来的数据加上一个信息头。接收方每一层会把信息头去掉。

对等层之间互相通信需要遵守一定的规则,如通信的内容和通信的方式,这种规则称为网络协议。

OSI模型各层典型协议:书P8

TCP/IP参考模型分为4个层次:应用层、传输层、网络互联层和主机-网络层。

TCP/IP参考模型各层协议:书P9

TCP协议:面向连接的、可靠的协议。

UDP协议:不可靠的、无连接协议。

IP协议:IP地址(IP网址+IP主机地址),网络掩码与IP地址进行二进制与操作,得到的结果就是IP网址。

DNS协议采用DNS服务器来提供把域名转换为IP地址。

TCP采用端口区分进程。TCP连接的两个端点用端口来标识。

每个进程有了唯一的地址,TCP就能保证把数据顺利送达特定的进程。

端口号的范围为0655350-1023操作系统保留。

服务端端口号需要指定,客户端端口号一般系统动态分配。

TCPUDP都用端口来标识进程,取值范围各自独立,允许存在取值相同的TCP端口和UDP端口。

客户/服务器模式,一个服务器进程会同时为多个客户进程服务。

常用服务及端口,书17页。

传输层向应用层提供了套接字Socket接口,Socket封装了下层数据传输细节,应用层程序通过Socket来建立与远程主机的连接,以及进行数据传输。

Java中有3种套接字类:SocketServerSocketDatagramSocket

SocketServerSocket建立在TCP协议上,DatagramSocket建立在UDP协议上。

第2章 Socket用法详解

客户/服务器通信模式中,客户端需要主动创建与服务器连接的Socket,服务端收到客户端连接请求,也会创建与客户连接的Socket

等待建立连接的超时时间,默认情况下会一直等待下去,通过不带参数的Socket构造方法可以设定等待时间,单位毫秒,为0表示永远不会超时。

设定服务器地址,InetAddress

设定客户端地址,Socket对象既包含服务器IP和端口也包括客户端地址和端口,对于拥有多个IP地址的客户端可指定使用哪个IP

客户端连接服务端的异常:UnknownHostException(无法识别主机名或IP地址)ConnectionException(服务端没有监听指定端口或者拒绝连接)SocketTimeoutException(连接超时)BindException(无法把Socket对象与客户端IP或端口绑定),详见ConnectTester

getInputStreamgetOutputStream:如果Socket还没有连接或者已经关闭,或者已经调用shutdownInput(shutdownOutput)方法,则关闭输入输出流。

当通信结束,应及时通过close方法关闭Socket。强烈建议放在finally代码中确保总是执行。

Socket状态:isClose(如果已连接到远程主机,且还未关闭,返回true)isConnected(如果曾经连接到远程主机,返回true),isBound(如果已经与一个本地端口绑定,则返回true

半关闭Socket,结束通信的几种方式:书33

(1) 字符流:约定特殊字符

(2) 约定数据长度

(3) 发送方发完数据后,关闭Socket,这时接收端调用输入流的read方法返回值为-1

(4) 关闭输入或输出流,最终还需要调用Socketclose方法关闭Socket连接

isInputShutdownisOutputShutdown用于检测输入输出流状态

通信双方的终止方式:

(1) 自然结束

(2) 提前终止服务器端:服务器端突然结束,客户端会仍然会发送完全部数据后自然结束,这是因为服务器端底层Socket并没有立即释放,操作系统探测到还有发送给该端口的数据,会继续占用一断时间

(3) 突然终止客户端:抛出Connection reset异常

(4) 关闭或半关闭:服务器端抛出Connection reset异常

Socket选项:

TCP_NODELAY:是否立即发送数据,Negale算法,发送大批量数据,并且接收端及时响应的情况下很有用,如果是发送少量数据并且接收端不及时响应则会严重降低性能,采用该算法将把发送数据缓冲起来到一定大小后一次性发出,等待接收端响应后再发送下一批数据。

默认false采用该算法。

SO_RESUSEADDR:调用Socketclose方法关闭连接后,不会立刻端口,这时其他进程绑定到该端口将失败,设置SO_RESUSEADDRtrue将使得其他进程可以重用这个端口。必须在绑定到端口之前调用。一般是服务器端存在该问题。新进程不会收到之前的数据。

SO_TIMEOUT:接收数据的等待超时时间,单位毫秒,默认0表示永远等待。要在接收数据之前设置。

SO_LINGERSocket连接是否立即关闭

SO_SNFBUF:输出数据缓冲区大小,大批量数据建议大点,频繁传送小数据建议小点

SO_RCVBUF:输入数据缓冲区大小

SO_KEEPALIVE:为true时底层实现会监视连接有效性,客户端使用

OOBINLINE:为true时表示支持发送一个字节的紧急数据,一般不用。

服务类型:

IP规定了4中服务类型:

1、低成本:发送成本低

2、高可靠性:保证鲍数据可靠的发送到目的地

3、高吞吐量:一次接受发送大量数据

4、最小延迟:传输数据快,最快发送到目的地

设置服务类型:setTrafficClass(int trafficClass);

底成本:0x02

高可靠:0x04

最高吞吐量:0x08

最小延迟:0x10

连接时间、延迟、带宽的相对重要性:setPerformancePreference

第3章  ServerSocket用法详解

服务器端创建ServerSocket监听特定端口,ServerSocket负责接收客户连接请求。

ServerSocket三个参数:portbacklogbindAddr

绑定端口port:绑定失败将抛出BindException,可能由于端口已被占用或端口不能被该用户使用(例如1~1023可能只能用root用户绑定)所致,参数0表示操作系统分配,称为匿名端口。

客户连接请求队列的长度:客户端连接请求由操作系统的先进先出队列管理,ServerSocket通过accept方法取出该队列的请求,backlog用于改变请求队列长度,但是如果该值大于操作系统限制或小于等于0则依然使用操作系统的值。

设定绑定的IP地址:bindAddr参数,多IP时可以指定绑定到哪个IP

不带参数的构造器:创建完ServerSocket对象后需要调用bind方法,bind之前可以设置一些参数,有些参数必须在bind之前调用。

accept方法会阻塞,客户端连接上来后才返回。

ServerSocket不用close,程序结束时会释放,也可显示调用。

ServerSocketisClosedisBoundSocket类似。

获取服务器绑定IP和端口:getInetAddressgetLocalPort

FTP使用匿名端口

ServerSocket选项:

1. SO_TIMEOUTaccept等待客户端连接超时的时间,0表示永远不超时,一直等待客户端连接。

2. SO_REUSEADDR:和Socket的类似

3. SO_RCVBUF:接收数据的缓冲区的大小,与操作系统有关。

连接时间、延迟和带宽的相对重要性:与Socket类似

多线程服务器(重点)

前面的例子中的服务器都无法同时响应多个客户连接请求。

使用线程池注意事项书(74-76)

如何正确关闭服务器(76-80)

第4章 非阻塞通信

ServerSocketSocket运行过程中可能会阻塞,如果服务器需要与多个客户端通信,需要多个线程。每个线程都有可能处于长时间阻塞状态。利用JDK的非阻塞机制,服务器只需创建一个线程,就能完成同时与多个客户端通信。

线程阻塞:放弃CPU、暂停运行、等到阻塞的原因消除,才能恢复运行;或者被其他线程终端,该线程会退出阻塞状态,并且抛出InterruptedException

导致线程阻塞的原因:

(1) 线程执行了Thread.sleep

(2) 线程要执行一段同步代码,由于无法获得同步锁而进入阻塞状态

(3) 线程执行了一个对象的wait方法

(4) IO操作或远程通信时,等待资源而进入阻塞状态。

客户端可能阻塞的情况:

(1) 请求与服务器建立连接

(2) 线程从Socket的输入流读入数据

(3) 线程向Socket的输出流写一批数据

(4) 调用了setSoLinger方法设置了关闭Socket的延迟时间

服务端可能阻塞的情况:

(1) 线程执行ServerSocketaccept方法,等待客户端连接。

(2) 线程从Socket的输入流读入数据

(3) 线程向Socket的输出流写一批数据

阻塞IO和非阻塞IO:这种可能出现阻塞的称为阻塞IO,否则是非阻塞IO

服务器用多个线程响应客户端请求的局限性:

(1) 虚拟机会为每个线程分配独立的堆栈空间,线程越多,系统管理压力越大,单纯的增加线程并不能使性能持续上升。线程数量要合理,并不是越多越好。

(2) 许多时间浪费在阻塞IO上。

非阻塞思想:

服务器程序只需一个线程就能同时负责接收客户的连接、接收各个客户发送的数据,以及向各个客户发送响应数据。采用轮询方式,当某一种操作就绪时,就执行该操作,否则就查看是否还有其他就绪的操作可以执行。所谓非阻塞就是如果操作还没就绪,立即返回,而不会一直等到操作就绪。这时while循环是阻塞住的,一般有个特定的退出条件。

Java.nio包的非阻塞通信类:

ServerSocketChannelSocketChannel:支持阻塞非阻塞,代替ServerSocketSocket

Selector:为ServerSocketChannel监控连接就绪事件,为SocketChannel监控连接就绪、读就绪、写就绪事件。

SelectionKey:注册事件的句柄,当一个SelectionKey对象位于Selector对象的selected-keys集合中时,就表示与这个SelectionKey对象相关的事件发生了。

ByteBuffer:字节缓冲区。readwrite都把数据放入缓冲区中。需要用Charset转换。

缓冲区Buffer:书88

通道Channel:书90

SelectableChannel:书92

ServerSocketChannel:书93

SocketChannel:书93

Selector类:书96

SelectionKey类:书97

阻塞非阻塞模式总结:书127

第5章 创建非阻塞的HTTP服务器

参见源代码

第6章 客户端协议处理框架

通用协议处理框架封装了SocketJava对客户程序的通信过程进行了抽象,主要包括:URLURLConnectionURLStreamHandlerContentHandler类。后三个需要自己实现。对于一些常用协议JDK有相应实现,这个主要为了简化Socket操作。例如:JDKHTTP协议实现了协议处理框架。用户可以对于自己的协议进行实现。

第8章 基于UDP的数据报和套接字

TCP协议是网络传输层的一种可靠的数据传输协议。如果数据在传输途中丢失或损坏,TCP会保证再次发送数据:如果数据到达接收方的顺序被打乱,TCP会在接收方重新恢复数据的正确顺序。应用层无须担心接收到乱序或错误的数据。

TCP的可靠性是有代价的,这种代价就是传输速度的降低。建立和销毁TCP连接会花费很长的时间。如果通信双方实际上通信的时间很短,要传输的数据很少,那么建立和销毁TCP连接的代价就相对较高。

UDP,不可靠传输,传输速度快,传输单元称为UDP数据报,无法保证数据报一定到达目的地,也无法保证发送顺序。可以通过应用层协议保证可靠性。常用于即时通信,音频视频,NFSTFTP

UDP是无连接协议,交换数据无需建立连接。DatagramSocket负责接收和发送UDP数据报,DatagramPacket表示UDP数据报。

DatagramPacket类:

用于发送数据的构造方法需要设定数据报到达的目的地址,而用于接收数据的构造方法无需设定地址。一般是服务端无需地址,客户端需要指明数据报发送的目的地。

数据报大小:length参数决定了数据报的长度。如果收到的数据报大于该值,则多余部分丢弃。选择原则:网络越差,数据报应越小,反之则可以加大数据报长度,8KB是个好的折中方案。

数据格式:数据报中只能存放字节形式的数据。

重用DatagramPacket:详见代码

DatagramSocket类:

接收和发送数据报:sendreceive方法。

管理连接:只与特定DatagramSocket交换数据。connect方法。

关闭DatagramSocket

选项:

SO_TIMEOUT:接收数据报时的等待超时时间。单位毫秒,默认为0,永不超时。

SO_RCVBUF:接收数据的缓冲区的大小

SO_SNDBUF:发送数据的缓冲区的大小

SO_REUSEADDR:是否允许重用绑定地址,多个DatagramSocket是否可以绑定到相同的IP地址和端口,会复制给所有的DatagramSocket

SO_BROADCAST:是否允许对网络广播地址收发数据。

IP服务类型:和TCP相同。

posted @ 2012-09-13 14:59  流-星-追-月  阅读(163)  评论(0编辑  收藏  举报