11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)

1. OSI 和 TCP/IP模型对比

11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第1张图片
OSI : 为了促进计算机网络的发展,国际标准化组织ISO于1977年成立了一个委员会,在现有网络的基础上,提出了不基于具体机型、操作系统或公司的网络体系结构,称为开放系统互连参考模型,即OSI/RM (Open System Interconnection Reference Model)。OSI模型把网络通信的工作分为7层,分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。

  1. 物理层:物理层处于OSI的最底层,是整个开放系统的基础。物理层涉及通信信道上传输的原始比特流(bits),它的功能主要是为数据端设备提供传送数据的通路以及传输数据。
  2. 数据链路层:数据链路层的主要任务是实现计算机网络中相邻节点之间的可靠传输,把原始的、有差错的物理传输线路加上数据链路协议以后,构成逻辑上可靠的数据链路。需要完成的功能有链路管理、成帧、差错控制以及流量控制等。其中成帧是对物理层的原始比特流进行界定,数据链路层也能够对帧的丢失进行处理。
  3. 网络层:网络层涉及源主机节点到目的主机节点之间可靠的网络传输,它需要完成的功能主要包括路由选择、网络寻址、流量控制、拥塞控制、网络互连等。
  4. 传输层:传输层起着承上启下的作用,涉及源端节点到目的端节点之间可靠的信息传输。传输层需要解决跨越网络连接的建立和释放,对底层不可靠的网络,建立连接时需要三次握手,释放连接时需要四次挥手。
  5. 会话层:会话层的主要功能是负责应用程序之间建立、维持和中断会话,同时也提供对设备和结点之间的会话控制,协调系统和服务之间的交流,并通过提供单工、半双工和全双工3种不同的通信方式,使系统和服务之间有序地进行通信。
  6. 表示层:表示层关心所传输数据信息的格式定义,其主要功能是把应用层提供的信息变换为能够共同理解的形式,提供字符代码、数据格式、控制信息格式、加密等的统一表示。
  7. 应用层:应用层为OSI的最高层,是直接为应用进程提供服务的。其作用是在实现多个系统应用进程相互通信的同时,完成一系列业务处理所需的服务。

TCP/IP,即Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,是Internet最基本的协议、Internet国际互联网络的基础。TCP/IP参考模型采用4层的层级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求,这4个层次分别是:网络接口层、互联网层(IP层)、传输层(TCP层)、应用层。

  1. 网络接口层:TCP/IP协议对网络接口层没有给出具体的描述,网络接口层对应着物理层和数据链路层。
  2. 互联网层(IP层):互联网层是整个TCP/IP协议栈的核心。它的功能是把分组发往目标网络或主机。同时,为了尽快地发送分组,可能需要沿不同的路径同时进行分组传递。因此,分组到达的顺序和发送的顺序可能不同,这就需要上层必须对分组进行排序。互联网层除了需要完成路由的功能外,也可以完成将不同类型的网络(异构网)互连的任务。除此之外,互联网层还需要完成拥塞控制的功能。
  3. 传输层(TCP层):TCP层负责在应用进程之间建立端到端的连接和可靠通信,它只存在与端节点中。TCP层涉及两个协议,TCP和UDP。其中,TCP协议提供面向连接的服务,提供按字节流的有序、可靠传输,可以实现连接管理、差错控制、流量控制、拥塞控制等。UDP协议提供无连接的服务,用于不需要或无法实现面向连接的网络应用中。
  4. 应用层:应用层为Internet中的各种网络应用提供服务。

IP地址(Internet Protocol):唯一标识网络上的每一台计算机
IP地址的组成:32位,由4个8位二进制数组成
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第2张图片
IP地址 = 网络地址(标识计算机或网络设备所在的网段) +主机地址(标识特定主机或网络设备)
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第3张图片

2. 常见网络协议

下面这张图可以看出TCP/IP协议簇中不同的层次中有着很多不同的网络协议,下面主要介绍传输层的TCP、UDP协议和应用层的HTTP协议。
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第4张图片

1)TCP协议

TCP(Transmission Control Protocol ,传输控制协议)是面向连接的传输层协议。TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。TCP协议采用字节流传输数据。
TCP报文段包括协议首部和数据两部分,协议首部的固定部分有20个字节,首部的固定部分后面是选项部分。
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第5张图片
下面是报文段首部各个字段的含义:

  1. 源端口号以及目的端口号,各占2个字节,端口是传输层和应用层的服务接口,用于寻找发送端和接收端的进程,一般来讲,通过端口号和IP地址,可以唯一确定一个TCP连接,在网络编程中,通常被称为一个socket接口。

  2. 序号,占4字节,用来标识从TCP发送端向TCP接收端发送的数据字节流。

  3. 确认序号,占4字节,包含发送确认的一端所期望收到的下一个序号,因此,确认序号应该是上次已经成功收到数据字节序号加1.

  4. 数据偏移,占4位,用于指出TCP首部长度,若不存在选项,则这个值为20字节,数据偏移的最大值为60字节。

  5. 保留字段占6位,暂时可忽略,值全为0。

  6. 标志位
    URG(紧急) : 为1时表明紧急指针字段有效
    ACK(确认):为1时表明确认号字段有效
    PSH(推送):为1时接收方应尽快将这个报文段交给应用层
    RST(复位):为1时表明TCP连接出现故障必须重建连接
    SYN(同步):在连接建立时用来同步序号
    FIN (终止): 为1时表明发送端数据发送完毕要求释放连接

  7. 接收窗口占2个字节,用于流量控制和拥塞控制,表示当前接收缓冲区的大小。在计算机网络中,通常是用接收方的接收能力的大小来控制发送方的数据发送量。TCP连接的一端根据缓冲区大小确定自己的接收窗口值,告诉对方,使对方可以确定发送数据的字节数。

  8. 校验和占2个字节,范围包括首部和数据两部分。

  9. 选项是可选的,默认情况是不选。

三次握手与四次挥手

TCP是面向连接的协议,因此每个TCP连接都有3个阶段:连接建立、数据传送和连接释放。连接建立经历三个步骤,通常称为“三次握手”。
TCP三次握手过程如下:
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第6张图片

  • 第一次握手:客户机发送连接请求报文段到服务器,并进入SYN_SENT状态,等待服务器确认。(SYN = 1,seq=x)
  • 第二次握手:服务器收到连接请求报文,如果同意建立连接,向客户机发回确认报文段,并为该TCP连接分配TCP缓存和变量。(SYN=1,ACK=1,seq=y,ack=x+1)。
  • 第三次握手:客户机收到服务器的确认报文段后,向服务器给出确认报文段,并且也要给该连接分配缓存和变量。此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。(ACK=1,seq=x+1,ack=y+1)。

TCP四次挥手过程如下
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第7张图片
由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

  1. TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。
  2. 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
  3. 服务器关闭客户端的连接,发送一个FIN给客户端。
  4. 客户端发回ACK报文确认,并将确认序号设置为收到序号加1。
2)UDP协议

UDP,用户数据报协议,英文全称是User Datagram Protocol,它是TCP/IP协议簇中无连接的运输层协议。UDP协议的格式如下图所示:
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第8张图片
UDP协议十分简单,它由两部分组成:首部和数据。其中,首部仅有8个字节,包括源端口和目的端口,长度(UDP用于数据报的长度)、校验和。

3)HTTP协议

HTTP,超文本传输协议,英文全称是Hypertext Transfer Protocol,它是互联网上应用最为广泛的一种网络协议。HTTP是一种应用层协议,它是基于TCP协议之上的请求/响应式的协议,即一个客户端与服务器建立连接后,向服务器发送一个请求;服务器接到请求后,给予相应的响应信息。HTTP协议默认的端口号为80.

HTTP协议是基于TCP协议之上的请求/响应式协议,下面主要介绍HTTP报文的格式,HTTP报文主要有请求报文和响应报文两种。首先看请求报文的格式
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第9张图片
HTTP请求报文由请求行、首部行和实体主体组成,由浏览器发送给服务器。上面这张图中SP表示空格,cr lf表示回车和换行。

HTTP响应报文格式
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第10张图片
上面这张图是HTTP响应报文,它由状态行、首部行和实体主体组成。下面两张图是在谷歌浏览器内访问服务器查看的HTTP请求和响应。
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第11张图片
HTTP请求方法和响应状态码
在上面的HTTP请求报文例子中,我们可以看到请求方法是GET,这表示请求读取由URL所标志的信息,除了GET,还有其它几种常用的方法。
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第12张图片
在HTTP响应报文的例子中,我们可以看到状态码是200,表示响应成功。下表是其它状态码,总共5大类,33种。
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第13张图片
HTTP请求的GET方法和POST方法的区别?
GET和POST是HTTP请求的两种方法,主要区别在于GET方法是请求读取由URL所标志的信息,POST是给服务器添加信息

HTTPS和HTTP的区别
HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。
HTTPS和HTTP的区别主要为以下四点:

  • 1、https协议需要到ca申请证书,一般免费证书很少,需要交费。
  • 2、http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
  • 3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  • 4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

3. Java网络编程

Socket编程:Java的网络编程主要涉及到的内容是Socket编程,Socket,套接字,就是两台主机之间逻辑连接的端点。TPC/IP协议是传输层协议,主要解决数据如何在网络中传输,而HTTP是应用层协议,主要解决如何包装数据。Socket,本质上就是一组接口,是对TCP/IP协议的封装和应用(程序员层面上)。
整体流程:Socket编程主要涉及到客户端和服务器端两个方面,首先是在服务器端创建一个服务器套接字(ServerSocket),并把它附加到一个端口上,服务器从这个端口监听连接。端口号的范围是0到65536,但是0到1024是为特权服务保留的端口号,我们可以选择任意一个当前没有被其他进程使用的端口。
客户端请求与服务器进行连接的时候,根据服务器的域名或者IP地址,加上端口号,打开一个套接字。当服务器接受连接后,服务器和客户端之间的通信就像输入输出流一样进行操作。
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第14张图片
下面是一个客户端和服务器端进行数据交互的简单例子,通过这个例子可以初步对Socket编程有个把握。

/**
 * 服务器端
 */
public class Server {
    public static void main(String[] args) throws IOException {
        try {
            //创建一个Socket,接收客户端请求,监听5000
            ServerSocket serverSocket = new ServerSocket(5000);
            System.out.println("服务器启动成功,等待用户接入…");
            //使用accept()侦听并接收到此ServerSocket的连接
            Socket socket = serverSocket.accept();//侦听到之前都是阻塞的
            System.out.println("有客户端接入,客户IP:" + socket.getInetAddress());

            // 从客户端生成网络输入流,用于接收来自网络的数据
            InputStream is = socket.getInputStream();
            // BufferedReader读取字符流
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String info;
            // BufferedReader的方法可以一行一行的读
            while((info = br.readLine())!=null){
                System.out.println("客户端:"+info);
            }
            //给客户端一个响应
            String reply = "欢迎登陆";
            //通过输出流将响应发送回给客户端
            OutputStream os = socket.getOutputStream();
            os.write(reply.getBytes());
            //释放相应资源
            os.close();
            br.close();
            is.close();
            socket.close();
            serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

/**
 * 客户端
 */
public class Client {
    public static void main(String[] args) throws IOException {
        //创建一个客户端的Socket
        try {
            Socket socket = new Socket("localhost",5000);
            System.out.println("连接服务器成功");
            //通过输出流发送请求
            //直接输出数据流
            String info = "用户名:张三;密码:123456";
            // 从客户端生成网络输出流,用来把数据发送到网络上
            OutputStream os = socket.getOutputStream();
            //打散成数据数组
            byte[] infos = info.getBytes();
            os.write(infos);
            //关闭输出流,这是一个半关闭
            socket.shutdownOutput();
            //通过输入流接收服务器给我的响应
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String reply;
            while((reply = br.readLine())!=null){
                System.out.println("服务器:"+reply);
            }
            //释放资源
            os.close();
            socket.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

先启动服务器端,再启动客户端,测试代码如下图所示:
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第15张图片
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第16张图片
下面以一个例子介绍:实现服务器和客户端的多线程连接;并且服务器和客户端可以无限对话。

import java.io.*;
import java.net.*;
import java.util.Scanner;

/**
 * 接收客户请求,基于客户一个响应:线程构造方法中去绑定客户端的Socket
 */
public class LogicThread extends Thread {
    private Socket socket;
    public LogicThread(Socket socket){
        this.socket=socket;
    }
    //接收客户请求,基于客户一个响应
    public void run(){
        InputStream is=null;
        BufferedReader br=null;
        PrintWriter pw=null;
        OutputStream os=null;
        try{
            Scanner input = new Scanner(System.in);
            //获得输入流,获得用户的请求
            while(true){
                is= socket.getInputStream();
                br = new BufferedReader(new InputStreamReader(is));
                System.out.println(socket.getInetAddress()+"说:"+br.readLine());
                //给客户端一个响应
                //通过输出流将响应发送回给客户端
                String reply =input.next();
                os = socket.getOutputStream();
                pw = new PrintWriter(os);
                pw.println(reply);
                pw.flush();
            }
            //释放相应资源
        }catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                pw.close();
                os.close();
                br.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

import java.io.*;
import java.net.*;

/**
 * 监听客户请求:一旦监听到有客户请求,立即创建一个线程,开启线程
 */
public class LogicServicer {
    public static void main(String[] args) {
        try {
            //接收客户端请求
            //创建一个Socket
            ServerSocket serverSocket = new ServerSocket(8848);
            System.out.println("服务器已启动...");
            //使用accept()侦听并接收到此ServerSocket的连接
            //一直监听客户请求
            while(true){
                Socket socket = serverSocket.accept();//侦听到之前都是阻塞的
                System.out.println("已连接");
                //创建一个和该客户端响应的线程
                LogicThread logicThread = new LogicThread(socket);
                logicThread.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

import java.io.*;
import java.net.*;
import java.util.Scanner;

/**
 * 客户端:发送请求到服务器,接收服务器的响应
 */
public class LogicClient {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        OutputStream os=null;
        PrintWriter pw=null;
        InputStream is=null;
        BufferedReader br=null;
        //创建一个客户端的Socket
        try {
            Socket socket = new Socket("localhost",8848);
            System.out.println("客户端已启动");
            //通过输出流发送请求
            while(true){
                String info =input.next();
                os = socket.getOutputStream();
                pw = new PrintWriter(os);
                pw.println(info);
                pw.flush();
                //通过输入流接收服务器给我的响应
                is = socket.getInputStream();
                br = new BufferedReader(new InputStreamReader(is));
                System.out.println("服务器:"+br.readLine());
            }
            //释放资源
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                os.close();
                pw.close();
                br.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            } 
        }
    }
}

先启动服务器,再启动客户端,客户端和服务器对话结果如下图所示:
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第17张图片
11 java网络编程总结(包括网络模型的对比,常见网络协议如TCP,UDP,HTTP的介绍,Socket编程及案例)_第18张图片

你可能感兴趣的:(java语言核心总结,Java语言编程)