计算机网络将地理位置不同的计算机通过通信线路连接起来,实现资源的共享和信息的传递,网络中的计算机通常称之为主机,而网络编程就是通过程序来实现两台以上主机之间的通信。 实际的通信网络内容较多,但是Java语言提供了许多网络类,屏蔽了底层的复杂细节,是程序员可以很容易地编写出网络程序。
在进行Java网络编程之前,需要对关于计算机网络的总体知识有一个大致的理解。
众所周知,计算机网络传输实际上是一个很复杂的模型,为了更方便程序开发,我们一般会简历网络传输模型,将各个不同的层次分隔开,由不同的人来设计不同的层次,这样设计各个层次的人就不用管其他层面的具体实现,每一层都呼叫它的下一层所提供的网络来完成自己的需求,只需要调用别人的服务就可以了,大大提高了工作效率。除此之外,因为各层之间是独立的,结构上可分割开,所以灵活性好,易于实现和维护,能促进标准化工作:差错控制,流量控制,分段和重装,复用和分用,连接建立和释放。
常见的模型由三种:
5层只是OSI和TCP/IP的综合,是业界产生出来的非官方协议模型,但是很多具体的应用。实际应用还是TCP/IP的四层结构。
该体系将数据链路层和物理层合并为网络接口层。
OSI总结图 TCP/IP协议与其的关系() 这是其中有关于协议的数据报文格式:
计算机在网络通信协议中必须遵守一定的规则,就好比车辆行驶要遵守交通规则一样,在计算机网络协议中,这些连接和通信的规则被称为网络通信协议,它对传输格式,传输速率,传输步骤做了统一的规定,通信双方必须遵守这些协议才能进行数据交换;
网络通信协议有很多种,但是目前主要使用的还是TCP/IP、UDP、ICMP和一些其他协议;
要想使计算机能够通信,必须要为每台计算机指定标识号,通过标识号来指定接收或发送数据的计算机,在TCP/IP协议中,这个标识号就是IP地址,目前普遍使用的是4个字节的IPV4,不过为了解决日渐枯竭的网络地址资源不足,现在16个字节IPV6也应运而生;
IP地址一般由两部分组成,是 网络号+主机号,网络号指定网络地址,主机号指定该网络中的主机地址,二者是主从关系;
通过IP地址可以连接到指定计算机,但是如果想要访问计算机中某个应用程序,还需要指定端口号,在计算机中,不同的应用程序是通过端口号来区分的,端口号是用两个字节(16位的二进制数)来表示的,取值范围为0到65533,但其中0到1023的端口号被系统的网络服务所占有,所以用户的普通应用的端口号不能属于这个范围;
总得来说,一台计算机可以通过IP地址来访问到网络中的另一台计算机,并通过端口号来访问这个计算机中的某个应用程序;
这是Java中提供的与IP地址相关的InetAddress类,该类用于封装IP地址,并提供了一系列与IP地址相关的方法,该类的方法有以下几个,例如:
InetAddress getByName(String host) 得到IP地址封装为InetAddress类 InetAddress getLocalHost() 创建一个表示本地主机的InetAddress对象 String getHostName() 得到字符串格式的原始IP地址 String getHostHome() 得到确定的IP地址的主机名 boolean isReachable(int timeout) 判断在指定的时间内地址是否可以到达TCP和UDP是两个传输层的高级协议;
UDP是用户数据报协议,TCP是传输控制协议;
UDP是无连接通信协议,在数据传输的时候,数据的发送端和接收端并不建立逻辑连接,简单来说,当一台计算机向另外一台计算机发送数据时,并不好确认接收端是否存在,就直接发送数据,接收端在接受数据的时候,也不会向发送端反馈是否收到数据。 由于UDP消耗资源小,传输效率高,,所以通常用于音视频和普通数据的传输,比如说直播视频,但是由于UDP的无连接性,不能保证数据传输的完整性,所以在传输重要数据的时候不建议使用UDP。
TCP是面向连接的通信协议,即在传输数据的时候先在发送端和接收端建立逻辑连接,然后再传输数据;这提供了两台计算机之间可靠的,无差错的数据传输; 由于TCP的面向连接的特性,它可以保证数据传输的安全性,所以是一个被广泛采取的协议,比如在下载压缩包文件的时候,就非常适合使用TCP连接。
在TCP连接过程中,必须要明确客户端和服务器端,由客户端来向服务器端发出连接请求; 每次连接都需要经历三次握手协议; 三次握手协议: 第一次握手,客户端向服务器端发出连接请求,等待服务器端的确认; 第二次握手,服务器端向客户端回复一个响应,通知客户端收到了连接请求; 第三次握手,客户端向服务器端发送确认信息,确认连接;
而在TCP断开链接的时候,就需要用到四次挥手协议 第一次挥手,若A认为数据发送完成,则它需要向B发送连接释放请求。 第二次挥手,B收到连接释放请求后,会通知相应的应用程序,告诉它A向B这个方向的连接已经释放。 第三次挥手,当B向A发完所有数据后,向A发送连接释放请求 第四次挥手,A收到释放请求后,向B发送确认应答。
TCP协议作为一个可靠的面向流的传输协议,其可靠性和流量控制由滑动窗口协议保证,而拥塞控制则由控制窗口结合一系列的控制算法实现,以及快重传和快恢复,超时重传来确保文件完整性。
两者所在层次: 两者特点比较:
用于建立TCP连接,该类可以实现一个服务端的程序;
1、构造ServerSocket
ServerSocket()throws IOException //ServerSocket有一个不带参数的默认构造方法。通过该方法创建的ServerSocket不与任何端口绑定,接下来还需要通过bind()方法与特定端口绑定,这个默认构造方法的用途是,允许服务器在绑定到特定端口之前,先设置ServerSocket的一些选项。因为一旦服务器与特定端口绑定,有些选项就不能再改变了。 ServerSocket(int port) throws IOException //使服务器与特定端口绑定,该端口由参数port指定 ServerSocket(int port, int backlog) throws IOException //参数backlog指定客户连接请求队列的长度 ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException //参数bindAddr指定服务器要绑定的IP地址2.使用ServerSocket进行服务端编程
import java.io.*; import java.net.*; import java.util.*; public class qwe { public static void main(String[] args) { ServerSocket server = null; //创建服务器Socket对象 Socket socket = null; //创建Socket对象,用于接收另一端socket的连接 DataInputStream in = null; DataOutputStream out = null; //准备好IO流 int port = 5050;//设置端口号 try{ server = new ServerSocket(port); } catch (IOException e){ System.out.println(e); }//创建ServerSocket对象,绑定5050端口 try{ System.out.println("服务器启动"); socket = server.accept();//准备监听Socket连接并接收 in = new DataInputStream(socket.getInputStream());//返回一个输入流对象 out = new DataOutputStream(socket.getOutputStream());//返回一个输出流对象 //socket之间是通过IO流来交互信息的 String str = in.readUTF(); System.out.println("收到信息为:"+str); out.writeUTF("你好"); }catch(Exception e){ System.out.println(e); } finally { //准备关闭连接 try{ out.close(); in.close(); socket.close();//Socket对象的关闭连接方法 server.close(); }catch (Exception e){ System.out.println(e); } } } }UDP是一种无连接的不可靠传输协议,在使用UDP进行网络连接通信的时候,不需要建立连接,所以速度块,发送的时候需要封装成数据包,就像把信件装入信封。
UDP通信过程中并不建立连接,就像是两个货运公司在两个码头之间运送货物一样,在码头发送和接受货物都需要使用集装箱来装载货物。UDP通信也是一样,我们需要使用DatagramPacket类,该类的实例对象就相当与一个集装箱,也可以说是一个信封,我们就利用这个东西对我们需要发送的文件进行打包发送,总之,这个类是用来发送的。
构造方法: DatagramPacket(byte[] data, int length) //指定了封装信息的字节数组大小,以及数组的长苏 DatagramPacket(byte[] data, int offset, int length) //在上面的基础上,增加了offset,用于指定数据的缓冲位置 DatagramPacket(byte[ ] data, int length, InetAddress address, int port) //增加了指定的目标IP地址address和目的端口号port DatagramPacket(byte[] data, int offset, int length, InetAddress address, int port) //完整版 常用方法: InetAddress getAddress() //返回IP地址 int getPort() //返回端口号 byte[] getData() //返回打包的数据 int getLength() //返回数据字节数组的长度如果说DatagramPacket相当于一个集装箱,然而,两个货运公司之间的传输仅仅使用集装箱是不够的,我们还需要一个码头进行接收集装箱,在Java中,我们使用DatagramSocket来当作“码头”,使用该类的实例对象就可以接收或发送DatagramPacket数据包,总之,这个类是用来接收的。
构造方法: DatagramSocket() //用于创建一个DatagramSocket对象,如果没有给端口号,系统会从其他应用自动分配一个 DatagramSocket(int port) //指定了端口号,这样对象可以监听指定的端口 DatagramSocket(int port,InetAddress addr) //指定了端口号和IP地址,该对象适用与计算机上有多块网卡的情况,因为计算机针对不同的网卡会分配不同的IP地址,所以指定IP地址就可以确定你到底要使用哪块网卡来通信 void receive(DatagramPacket p) //接收包 void send(DatagramPacket p) //发送包 void close //关闭