黑马程序员 第四篇 Java 网络编程 (Foundation; completed)

来源:互联网 发布:表示公司的顶级域名 编辑:程序博客网 时间:2024/05/21 14:24

——- android培训、java培训、期待与您交流! ———-

1. 网络编程

1.1 TCP/IP协议

这里写图片描述

这里写图片描述

1.2 网络编程模型

这里写图片描述

网络编程目前有两种主要的模型,分别是C/S结构和B/S结构、

C/S结构是指客户机/服务器结构。所谓C/S结构,指的是在客户端需要安装客户端软件,由客户端软件负责与服务器端的数据通信,将任务合理分配到客户端和服务端实现,降低了网络的负载开销。

B/S结构是指浏览器/服务器结构。客户端只需要安装网页浏览器,不需要安装客户端软件,大部分逻辑事务处理在服务器端完成,客户端浏览器只完成少量的事务处理,减少了客户端的计算机负载,减轻了系统维护与升级的成本和工作量。

Java这样的跨平台语言出现之后,B/S架构管理软件更是方便,快捷,高效。

1.3 网络传输协议

这里写图片描述

UDP

UDP 与 TCP 的主要区别在于 UDP 不一定提供可靠的数据传输。事实上,该协议不能保证数据准确无误地到达目的地。UDP 在许多方面非常有效。当某个程序的目标是尽快地传输尽可能多的信息时(其中任意给定数据的重要性相对较低),可使用 UDP。ICQ 短消息使用 UDP 协议发送消息。 许多程序将使用单独的TCP连接和单独的UDP连接。重要的状态信息随可靠的TCP连接发送,而主数据流通过UDP发送。

TCP

TCP的目的是提供可靠的数据传输,并在相互进行通信的设备或服务之间保持一个虚拟连接。TCP在数据包接收无序、丢失或在交付期间被破坏时,负责数据恢复。它通过为其发送的每个数据包提供一个序号来完成此恢复。记住,较低的网络层会将每个数据包视为一个独立的单元,因此,数据包可以沿完全不同的路径发送,即使它们都是同一消息的组成部分。这种路由与网络层处理分段和重新组装数据包的方式非常相似,只是级别更高而已。为确保正确地接收数据,TCP要求在目标计算机成功收到数据时发回一个确认(即 ACK)。如果在某个时限内未收到相应的 ACK,将重新传送数据包。如果网络拥塞,这种重新传送将导致发送的数据包重复。但是,接收计算机可使用数据包的序号来确定它是否为重复数据包,并在必要时丢弃它。

TCP与UDP的选择

如果比较UDP包和TCP包的结构,很明显UDP包不具备TCP包复杂的可靠性与控制机制。与TCP协议相同,UDP的源端口数和目的端口数也都支持一台主机上的多个应用。一个16位的UDP包包含了一个字节长的头部和数据的长度,校验码域使其可以进行整体校验。(许多应用只支持UDP,如:多媒体数据流,不产生任何额外的数据,即使知道有破坏的包也不进行重发。) 很明显,当数据传输的性能必须让位于数据传输的完整性、可控制性和可靠性时,TCP协议是当然的选择。当强调传输性能而不是传输的完整性时,如:音频和多媒体应用,UDP是最好的选择。在数据传输时间很短,以至于此前的连接过程成为整个流量主体的情况下,UDP也是一个好的选择,如:DNS交换。把SNMP建立在UDP上的部分原因是设计者认为当发生网络阻塞时,UDP较低的开销使其有更好的机会去传送管理数据。TCP丰富的功能有时会导致不可预料的性能低下,但是我们相信在不远的将来,TCP可靠的点对点连接将会用于绝大多数的网络应用。

TCP协议和UDP协议特性区别总结:

 1. TCP协议在传送数据段的时候要给段标号;UDP协议不 2. TCP协议可靠;UDP协议不可靠 3. TCP协议是面向连接;UDP协议采用无连接 4. TCP协议负载较高,采用虚电路;UDP采用无连接 5. TCP协议的发送方要确认接收方是否收到数据段(3次握手协议) 6. TCP协议采用窗口技术和流控制

本节参考自
http://feinibuke.blog.51cto.com/1724260/340272/

1.4 端口和套接字

这里写图片描述

这里写图片描述

2. 基于TCP/IP协议的网络编程

2.1 Socket套接字

Socket 套接字是基于TCP/IP协议的编程接口,用于描述IP地址和端口,是一个通信链的句柄。应用程序通过Socket套接字向网络发送请求应答网络请求。

Socket有两种主要的操作方式,包括面向连接的和无连接的

这里写图片描述

面向连接的Socket操作就像人们打电话,必须先拨号码,建立一个连接,然后再对话。数据包在到达接收端时的顺序与它们出发时的顺序一样,就像一个人在电话中对另外一个人说话一样,每一个字到达另一个端的时候与它发出时的顺序一样。

无连接的Socket操作就像邮递员送信,邮递员只负责把信送出,至于何时发出,最后能不能到达收信人手中不能保证,无连接的Socket操作也一样,负责发出,但不保证数据包的传输质量,数据包到达目的地的顺序可能与发出时顺序不一样。

2.2 ServerSocket类

Java中的网络编程时通过ServerSocket类和Socket类结合使用来完成的。

ServerSocket类是应用在服务器端的类,一般用来监听指定的端口并接受客户端的连接请求。在服务器端,由ServerSocket类负责实现服务器套接字,ServerSocket类位于java.net包中。

ServerSocket类的构造器

public ServerSocket() throws IOExceptionpublic ServerSocket(int port) throws IOExceptionpublic ServerSocket(int port, int backlog) throws IOExceptionpublic ServerSocket(int port, int backlog, InetAddress bindAddr)throws IOException

Tips:

同一台主机上的同一端口号稚嫩而过分配给一个特定的ServerSocket对象,不能两个ServerSocket对象监听同一个端口。端口号的理论范围为0-65535,但前1024个中的大部分已经分配给了特定的应用协议,所以不能选用。

下面代码使用一个ServerSocket类

import java.net.*;public class JavaNet{    public static void main(String[] args)    {        try        {            ServerSocket ss = new ServerSocket(9876);        }        catch(Exception e)        {        }    }}

ServerSocket常用的方法

accept方法
使用该方法接受客户端的连接请求,并将与客户端的连接封装成一个Socket对象返回。此方法为阻塞方法,在没有接受到任何连接请求前调用此方法的线程讲一直阻塞等待,直到接收到连接请求后此方法才返回,调用此方法的线程才继续运行。

除了accept方法外还有一个close方法可以关闭ServerSocket对象使用getLocalPort方法获取设置的端口号。

2.3 Socket类

Socket类表示套接字。使用Socket时,需要指定待连接服务器的IP地址及端口号。

Socket类的常用构造器

public Socket(String host, int port)throws UnknownHostException, IOExceptionpublic Socket(inetAddress address, int port)throws IOException

使用Socket类的程序

import java.net.*;public class JavaSocket{    public static void main(String[] args)    {        try        {            Socket s = new Socket("192.168.1.119", 9876);            s.close();        }        catch(Exception e)        {        }    }}

Socket类中同样具有一些方法。其中,getPort方法和getLocalPort方法分别是获取连接的远端接口和使用的本地端口getInputStream方法和getOutputStream方法分别是获取*Socket对象的输入流和输出流*。

Tips
close方法虽然是很简单的,表示关闭Socket对象。但是该方法在程序中是必须有的,这是一个非常好的网络编程习惯。

2.4 网络编程C/S架构实例

C/S构架的网络编程程序是由服务器端和客户端组成的。Java中的网络编程主要是围绕socket来进行的,在服务器端要建立一个ServerSocket开发一个端口,对客户端进行服务,在客户端要建立一个socket通过IP和服务器端开发的端口访问服务器。

一个运行在服务器端的程序

import java.io.*;import java.net.*;import java.util.*;public class JavaNet{    public static void main(String[] args)    {        int count = 0;        try        {            //创建绑定到9876端口的ServerSocket对象            ServerSocket server = new ServerSocket(9876);            System.out.println("服务器对9876端口正在进行监听");            //服务器循环接收客户端的请求,为不同的客户端提供服务            while(true)            {                //接收客户端的连接请求,若有连接请求返回连接对应的socket对象                Socket sc = server.accpeet();                //获取当前连接的输入流,并使用处理流进行封装                DataInputStream din = newDataInputStream(sc.getInputStream());                //获取当前连接的输出流,并使用处理流进行封装                DataOutputStream dout = new DataOutputStream(sc.getOutputStream());                //打印客户端信息                System.out.println("这是第"+(++count)+"个客户访问");                        System.out.println("客户端ip地址: "+ sc.getInetAddress());                System.out.println("本地端口号:   "+sc.getLocalPort());                System.out.println("客户端信息: "+din.readUTF());                //向客户端发送回应信息                dout.writeUTF("服务器的时间为: "+(new Date())+"。");                //关闭流                din.close();                dout.close();                //关闭此socket连接                sc.close()        }        catch(Exception e)        {            e.printStackTrace();        }    }}
import java.io.*;import java.net.*;public class JavaNet2{    public static void main(String[] args)    {        try        {            Socket sc = new Socket("192.168.1.119", "9876");            DataInputStream din = new DataInputStream(sc.getInputStream());            DataOutputStream dout = new DataOutputStream(sc.getOutputStream());            dout.writeUTF("Hello");            System.out.println(din.readUTF);            //关闭流            din.close();            dout.close();            //关闭此socket连接               sc.close();        }        catch(Exception e)        {            e.printStackTrace();        }    }}

——- android培训、java培训、期待与您交流! ———-

0 0
原创粉丝点击