Java 网络编程之 (完全总结)

来源:互联网 发布:mysqlfront导入数据库 编辑:程序博客网 时间:2024/04/29 16:46

TCP

 

      TCP,传输控制协议(Transmission Control Protocol),是面向连接的通信协议。它提供两台计算机之间的可靠无差错的数据传输。应用程序通过 TCP 进行通讯时,数据源和接收目标之间会建立一个虚拟的连接,这个连接一旦建立,两台计算机之间就可以把数据作为双向字节流进行交换。其实基于 TCP 的通信传输的数据帧也不是可靠的,只是在发送 TCP 数据帧的时候,接收端每次接收到数据以后就会进行差错验证,如果没有任何问题,就会回馈发送端一个数据帧,告诉它接收成功,发送端就会继续发送第二个数据包。通过这样的问答方式就保证了 TCP 传输数据的无差错性。这种行为是靠驱动程序的底层协议来完成的。

 

UDP

 

      UDP,用户数据报协议(User Datagram Protocol),是面向无连接的通信协议。它是一个无连接的通信协议,UDP 不保证用户数据的可靠性传输,但能向若干个目标发送数据,和接收若干个数据源的数据。如果一台主机向另一台主机发送 UDP 数据,这个数据会立即发送出去,而不管另一台主机是否准备好接收数据。当网络状态异常的时候,会造成 UDP 数据报的丢失。如果另外一台主机接收到了数据,它不会确认是否收到。

 

      

 

 

Socket

 

       是网络驱动层提供给应用程序编程接口和一种机制。我们可以把 Socket 比喻成是一个港口码头。应用程序只要把货物放到港口码头上,就算完成了货物的运送。对于接收方应用程序也要创建一个港口码头,只需要等待货物到达码头后将货物取走。

 

        Socket 是在应用程序中创建的,它是通过一种绑定机制与驱动程序建立关系,告诉自己所对应的 IP 和 Port。在网络上传输的每一个数据帧,必须包含发送者的 IP 地址和端口号。创建完 Socket 以后,应用程序写入到 Socket 的数据,由 Socket 交给驱动程序向网络上发送数据,计算机从网络上收到与某个 Socket 绑定的 IP 和 Port 相关的数据后,由驱动程序再交给 Socket ,应用程序就可以从这个 Socket 中读取接收到的数据。网络应用程序就是这样通过 Socket 发送和接收的。

 

        Socket 数据发送过程:

 

       

                1、由应用程序产生一个 Socket。

                2、应用程序调用 bind() 方法,将 Socket 的信息通知给驱动程序。这个 Socket 的信息主要是包括 IP 地址和端口号。

                3、应用程序向 Socket 中写入数据数据。

                4、驱动程序从 Socket 中取出数据,并通过网卡发送数据。

 

 

           Socket 数据接收过程:

 

 

        

 

              1、由应用程序产生一个 Socket。

              2、应用程序调用 bind() 方法,将 Socket 的信息通知给驱动程序。

              3、如果驱动程序收到的数据包中,包含了这个 Socket 所包含的 IP 和端口号,那么驱动程序就会把数据处理后传递给 Socket 中。

              4、当 Socket 当中有数据时,应用程序就将数据从 Socket 中取走。

 

 

Java 中的网络编程类

 

  • 位于 java.net 包中。
  • 用于 UDP 通信的 Socket 对应的是 DatagramSocket 类。
  • 用于 TCP 通信的 Socket 对应的是 ServerSocket 类。由于 TCP 程序分为客户端和服务器端,ServerSocket 是用于服务器端,Socket 类用于 TCP 通信的服务器和客户端。这个服务器端指的是专用于与客户端进行通信的 Socket ,ServerSocket 是用于接收客户端连接的 Socket。如果在创建 Socket 时没有指定端口号,系统就会为它分配一个其它网络程序还没有使用的端口号, 如果在创建 Socket 时没有指定 IP 地址,底层驱动程序会选择计算机上的任意一个 IP 地址作为发送源 IP 地址。对于一般只有一个 IP 地址的计算机不用指定 IP 地址。如果有多个网卡多个 IP 就应该指定特定IP 地址。

 

UDP 网络程序

 

     一、DatagramSocket 类(用于创建收发 UDP 数据报的对象)

 

           (1) 构造函数:

 

                       public DatagramSocket();   // 没有指定端口号和 IP 地址,接收方可以获取发送方使用的 IP 地址和端口号。


                       public DatagramSocket(int port);   // 如果有可能先接收数据。


                       public DatagramSocket(int port, InetAdderss Iaddr);   // 如果 UDP 程序运行在拥有多个 IP 地址的主机上。

 

           (2)DatagramSocket 的 close() 方法:

 

                       当应用程序不再需要使用 DatagramSocket 对象的时候,应该调用 close() 方法,以通知驱动程序释放对应的资源,系统就可以将这个 DatagramSocket 所对应的端口号交给其它应用程序使用。

 

           (3)send(DatagramPacket p) 方法:用于发送 DatagramSocket 对应的数据包

          

           (4)receive(DatagramPacket p) 方法:用于接收 DatagramSocket 对应的数据包

 

       二、DatagramPacket 类

 

               如果把 DatagramSocket 比作港口码头,那么 DatagramPacket 就是发送和接收数据的集装箱。

 

            (1)构造函数:

 

                        public DatagramPacket(byte[] buf, int length);  // 指定了数据包的缓冲区,和缓冲区的大小。(创建接收数据的 DatagramPacket 对象)


                        public DatagramPacket(byte[] buf, int length, InetAddress address, int port);  // 还指定了接收数据包目标计算机的地址和端口。(创建发送数据的 DatagramPacket 对象)

 

            (2)getInetAddress 和 getPort 方法:

 

                        当用于接收数据包的 DatagramPacket 对象,接收到了网络上发送过来的数据后,对方的  IP 地址和端口号也是封装在 DatapramPacket 当中的。

 

             (3)getData 和 getLength 方法:

 

                        当创建接收方的 DatagramPacket 对象时,因为无法预知对方发送的实际数据报的长度,一般都是定义了一个相对大的字节数组,来作为缓冲区,传递给 DatagramPacket 构造函数。getData() 方法就是获取内存缓冲区,也就是 buf 字节数组。getLength() 方法返回的是 DatagramPacket实际接收到的数据的长度。

 

 

        三、InetAddress 类

 

                   是用于表示计算机 IP 地址的类。

 

               (1)getByName() 静态方法。根据类似 “192.168.0.1” 这些字符串格式的计算机地址,返回一个 InetAddress 实例对象。

               (2)getHostAddress() 用于返回一个 InetAddress 对象当中封装的以 “.” 分割的字符串形式的 IP 地址。

 

         

        四、编程实例(1) - 编写发送端和接收端,并实现通信:

 

 

                发送端:

 

            

 

             接收端:

 

            

 

             运行结果:

 

            

 

 

             编程实例(2)基于 UDP 的网络聊天程序,可以实现外网聊天:

 

                我已经在我先前的博客中写了这个程序,地址:http://blog.csdn.net/DriverKing/archive/2011/06/26/6568793.aspx

 

 

TCP 网络程序

 

 

       一、TCP 网络程序工作原理:

 

            

 

               利用 UDP 两个通信的计算机是平等的,没有主从之分,而利用 TCP 两个进行通信的程序,是有主从关系的。一个称为服务器程序,另一个称为客户机程序。两者的功能和编写方法大不一样,

                  TCP 客户端与 TCP 服务器端程序的交互过程:

 

                        首先,由 TCP 服务器程序创建一个 ServerSocket 类,然后调用 accept() 方法等待客户端的连接。

                        其次,客户端程序创建一个 Socket 并请求与服务器建立连接。

                        接着,是服务器接收客户的连接请求,并创建一个与请求相关的新的 Socket 与客户机专线连接。

                        再次,建立连接的两个 Socket 在一个单独的线程(由服务器创建)上对话。

                        最后,服务器程序又开始等待新的连接请求,当新的连接请求到达时,它又会重复 2~5 的过程。

 

     

         二、ServerSocket 类

 

                      (1)构造函数:


                              public ServerSocket(); // 不能直接使用,必须调用它实例对象的 bind() 方法与绑定端口号或 IP

                           

                              public ServerSocket(int port); // 如果 port 等于 0 ,那么系统将自动分配一个未启用的端口号,作为 TCP 服务器最好确定端口号,这样客户机才能知道连接服务器的哪个端口。(一般用这个)


                              public ServerSocket(int port, int backlog); // 除了指定端口号外,还可以指定在服务器很忙的时候,可以与之保持连接请求的客户机数量。没有指定的话默认为 50。


                              public ServerSocket(int port, int backlog, InetAddress bindAddr); // 可以指定 ServerSocket 绑定的 IP 地址,适用于多个网卡或多个 IP。


                  (2)close 方法:


                              当程序不再使用 ServerSocket 对象时,应该调用 ServerSocket 的 close() 方法,将 ServerSocket 关闭,通知驱动程序释放所对应保留的资源。系统将会把这个端口号非配给其它应用程序使用。

 

                  (3)accept 方法:

 

                               程序调用 ServerSocket 对象的 accept() 方法,等待客户端的请求,一旦 accept() 方法接收了客户端的请求,这个方法就会返回一个与客户端建立了专线连接的 Socket 对象。

 

 

           三、Socket 类

 

                        (1)构造函数:

 

                               public Socket(); // 不能与任何服务器建立连接,需要调用 Socket 类的 connect( SocketAddress endpoint) 方法才可以使用。(用于一个客户机连接多个服务器)。

 

                               public Socket(String host, int port);

 

                               public Socket (InetAddress address, int port); // 第二个和第三个会根据 IP 和端口号去连接服务器。

 

                               public Socket(String host, int port, InetAddress localAddr, int localPort);

 

                               public Socket(InetAddress address, int port, InetAddress localAddr, int localPort); // 第四个和第五个增加了本地 IP 地址和端口号的绑定。

 

 

                     (2) getInputStream 和 getOutputStream 方法

 

                               getOutputStream() 方法用于返回 Socket 输入流的对象; getOutputStream () 方法用于返回 Socket 输出流的对象。Socket 的某一端只要向它的输出流对象中写入数据,那么另一端就能从自己的输入流对象中读取到数据。

 

 

          四、编程(1)编写完善的的 TCP 服务器客户端程序

 

                            此程序已经在先前的博客中写过,地址:http://blog.csdn.net/DriverKing/archive/2011/06/27/6569414.aspx

 

                    (2)编写服务器一对多的聊天程序

 

 

                             服务器端:

 

                      

 

 

                       客户端:

 

                      

 

 

    运行效果:

   

 

 

 

     五、在 TCP 网络连接上传递对象

 

 

            (1)ObjectInputStream 和 ObjectOutputStream 可以从底层输入流中读取对象类型的数据,和将对象类型的数据写入到底层输出流。

 

           (2)使用 Object InputStream 和 ObjectOutputStream 来包装底层网络字节流,TCP 服务器和 TCP 客户端之间就可以传递对象类型的数据。

 

 

             编程实例 :通过网络传输 Java 对象:

 

            


 

           

                     

 

URL(Uniform Resource Locator 统一资源定位符)

 

        (1)URL 的基本组成:协议、主机名、端口号、资源名。例如:http://bolg.csdn.net/driverking

 

          (2)相对 URL:一个相对的 URL 它不包括协议和主机,它表示 它的路径与当前文档或其它的 Internet 资源的主机名相同设置有相同的目录路径。

                “/a.htm” 表示与主机上某种协议的根目录。“../a.htm” 表示表示所在目录的父目录。“a.htm” 表示它是当前目录下的子目录。

 

          (3)URL 编码规则:例:将 “空格” 转换为 “+” 号。“0-9、a-z、A-Z” 保持不边,其它字符使用当前字符编码的内存中的十六进制格式表示。

 

 

HTTP 协议的会话过程

 

              现在广泛使用的 是 HTTP 1.1 版本, HTTP 1.1 相对于 HTTP 1.0 来说最大特点就是支持持久性的连接。

 

          (1)   HTTP 1.0 的连接过程 :浏览器到 Web 服务器之间的所有通信,都是完全独立分开的请求与相应对。这种通信过程总是由 Web 浏览器发送请求,Web 服务器被动的对请求进行响应。一次响应的处理时间与浏览器打开的时间没有关系,服务器向浏览器传送了请求响应后,这个连接就终结了。浏览器与服务器的连接是短暂的,只是在浏览器发出请求和服务器返回结果的期间,而不是持续到浏览器程序关闭。即使在一个页面不停的请求数据,你的每一次请求都是与服务器建立一个短暂的连接,而不是共享同一个连接。因此 HTTP 1.0 有性能上的缺陷。

          

 

          (2)HTTP 1.1 的连接过程 :当客户机发出第一次请求,然后服务器返回第一次请求的网页文档,浏览器在解析这个网页文档的过程中,发现又要去服务器请求第二次数据,那么它就会再次给服务器发出第二次请求,服务器就会返回第二次请求响应……第 n 次。并且浏览器不必等待一次的请求相应完毕,它就可以再一次的发送请求,这样大大的提高了网页文档的传送效率。客户机请求的信息和服务器响应的信息都称之为 HTTP 消息,HTTP 消息是有一定的格式和严格规定的。

         一个完整的请求消息包括:(1)一个请求行(2)若干消息头(3)实体内容。例如:

             

         GET www.baidu.com HTTP/1.1  (请求行,后面的内容都属于消息头部分)

         Accept: */*

         Accept-Language:en-us

         Connectino: Keep-Alive

         Host: localhost

         ……


        这个 HTTP 请求消息中没有实体内容,但是紧接着消息头后,必须有一个空行,这是用来分割消息头和实体内容的,可以来表示消息头部分已经结束。

 

        一个完整的响应消息包括:(1)一个状态行(2)若干个消息头(实体内容)。和请求消息一样,消息头和实体内容部分是可选的。消息头和实体内容之间必须有空行。例如:

 

        HTTP/1.1 200 OK

        Server:Microsoft-IIS/5.0

        Date:Thu, 13 Jul 2000 05:46:53 GMT

        Content-Length:2291(实体内容的长度,HTTP 1.1 必须包含该行)

        Content-Type:text/html

        Set-Cooike:……

          ……

 

          <html>

          <body>

 

          ……

          

 

          

 

         (3)几个常用的 HTTP 消息头

  • Connection 用于指定处理完本次请求/响应后,客户端与服务器是否继续保持连接。值可以为:Keep-Alive 或 close。HTTP 1.1 默认使用的是持久性连接。
  • Accept-Language 用于指定客户机期望服务器返回的文档所使用的国家语言,可以指定多个以逗号(,)分隔的国家语言。
  • Content-Length 用于表示实体内容的长度(字节数)
  • Range 用于指定服务器只需返回文档中的部分内容及部分内容的范围。(对于较大文档的断点续传非常有用)。有这样几种格式:

          1、Range: bytes=100-599(返回第100个字节和第599个字节之间的内容,包括了第100个和第599个,字节的顺序从 0 开始计算)

          2、Range: bytes=100- (返回文档中的第100个字节以后的所有内容)

          3、Range: bytes=-100 (返回文档中的最后100个字节的内容)

  • Content-Range 是与 Range 一起使用的,用于指定服务器返回的部分实体内容的位置信息。只有客户机使用了 Range 请求后,服务器才会返回 Content-Range 消息。例如:

          Content-Range: bytes 2543-4532/7898 (以 Byte 为单位的返回第 2543 - 4532之间的 的数据,7898表示总的实体内容的大小是 7898 个字节)

 

 

URL 类(表示 Internet 网络资源的 URL)

 

       (1)构造函数:

 

                    public URL(String sprc); // 直接使用表示 Internet 网络资源的 URL 字符串来创建 URL 对象。

 

                    public URL(String protocol, String host, int port, String file); // 使用协议名,主机名,端口号和资源本身的名称。

 

                    public URL(String protocol, String host, int port, String file, URLStreamHandler handler); // 多了一个对这种资源进行具体处理的协议处理器对象。

 

                    public URL(URL context, String spec); // 是在一个已有的 URL 对象基础上,再加上一个相对的 URL 字符文本来创建一个新的 URL 对象。例如 context 指向的是一个目录资源,spec 是这个目录下的文件名,这两者的组合就成了一个指向这个文件名的完整的 URl。

 

          (2)URL 类本身并不能获取网络资源中具体的内容,

 

          (3)openConnection 方法和 URLConnection 对象

 

                     openConnection() 方会调用协议处理器,也就是 URLStreamHandler的 openConnetion() 方法,返回一个 URLConnection 对象, URLConnection对象代表与这个 URL 指定的网络资源的连接,程序调用 URLConnectio() 的方法,就可以获取网络资源中的具体内容。

 

          (4)setURLStreamHandlerFactory(URLStreamhandlerFacoory fac) 静态方法

 

                 URLStreamhandlerFacoory 用于建立协议名和协议名对应处理器的关系。例如:在创建 URL 对象时指定的是 HTTP 那么它就应该调用 HTTP 协议处理器。

 

          (5)StreamHandlerFactory 类的 createURLStreamHandler(String protocol)

 

                 在创建 URL 对象时,Java 虚拟机会根据其中出现的协议名,调用 StreamHandlerFactory 对象中的  createURLStreamHandler(String protocol) 方法,将协议名传递进去,在方法内部,它会根据你传进来的协议名,创建出相应的协议处理器对象,然后返回给 URL 对象。


 

URLConnection 和 HTTPURLConnection 类

 

         URLConnection对象代表与这个 URL 指定的网络资源的连接,程序调用 URLConnectio() 的方法,就可以获取网络资源中的具体内容。URLConnection 本身并不能访问网络资源内容都是由它的子类完成的。 HTTPConnection 就是 URLConnection 的子类,

 

          (1) URLConnection 的连接过程

 

                 在产生 URLConnection对象后, URLConnection对象并没有真正的与 URL 对象指定的网络资源进行连接, 在这之前 URLConnection可以调用各种 set 方法来设置两者之间的连接参数和属性。

 

          (2)setRequestProperty() 用来设置各个协议的请求消息头。

 

          (3)getHeaderFields() 用来获取 HTTP 的响应消息头。

 

          (4)getInputStream 和 getOutputStream 分别返回用来读取 HTTP 响应实体内容的 InputStream 对象和 请求消息内容的 OutputStream 对象。

 

          (5)一个 HTTP 连接可以被多个 HttpURLConnection 实例对象共享,调用 HttpURLConnection的 disconnect() 方法可以关闭底层共享网络。

 

          编程实例:将访问 http://www.bing.com 站点的 HTTP 请求消息的 Accept-Language 头分别设置成日文和中文后,然后打印出 www.goolge.com 站点返回的所有响应消息头和网页内容

 

              

 

            

原创粉丝点击