java云同桌学习系列(十)——网络编程

本教程详细介绍了Java网络编程的基础知识,包括网络层次模型、TCP/IP协议、HTTP请求/响应、Socket编程及应用层协议。通过实例展示了如何使用ServerSocket和Socket进行C/S通信,以及URL、URLConnection的使用。此外,还涵盖了IP地址、URL编码解码和IDEA常用快捷键。学习本章将为深入理解网络编程打下坚实基础。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本博客java云同桌学习系列,旨在记录本人学习java的过程,并与大家分享,对于想学习java的同学,我希望这个系列能够鼓励大家一同与我学习java,成为“云同桌”。

每月预计保持更新数量三章起,每章都会从整体框架入手,介绍章节所涉及的重要知识点及相关练习题,并会设置推荐学习时间,每篇博客涉及到的点都会在开篇目录进行总览。(博客中所有高亮部分表示是面试题进阶考点)


学习时间:四天
学习建议:本章是一些网络编程的基础,需要认真弄明白基础知识点,未来开发的网络编程非常复杂,学习本章需要回顾之前的知识点,将IO流和多线程融入进来。


1.计算机网络基础

  • 按照作用范围的不同,计算机网络分为广域网(WAN)、城域网(MAN)、局域网(LAN)、个人区域网(PAN)
  • 带宽:在单位时间内网络中的某信道所能通过的“最高数据率”,单位bit/s
  • 吞吐量:单位时间通过某个网络的实际数据量,单位bit/s

互联网的组成:

1. 边缘部分:由所有连接在互联网上的主机组成,用户直接使用
2. 核心部分:由大量网络和连接这些网络的路由器组成,为边缘部分提供服务

边缘部分网络通信结构:

  • B/S结构
    B/S结构(Browser/Server,浏览器/服务器模式),是WEB兴起后的一种网络结构模式,WEB浏览器是客户端最主要的应用软件。例如:优快云博客系统…

  • C/S结构
    服务器-客户机,即Client-Server(C/S)结构。C/S结构通常采取两层结构。服务器负责数据的管理,客户机负责完成与用户的交互任务。例如:英雄联盟游戏系统…

(1)网络层次划分

在这里插入图片描述
在这里插入图片描述

(2)物理层

  • 物理层协议被称之为物理层规程

  • 信息交互的基本方式

    1. 单工通信:只能有一个方向的通信而没有反方向的交互
    2. 半双工通信:双方都可以发送接收,但不可以同时进行
    3. 全双工通信:可同时发送和接收信息

    注意,全双工的带宽=半双工的带宽,全双工的吞吐量=2×半双工的吞吐量。全双工的实际带宽=端口速率*2

  • 编码方式:

      1. 归零制
      2. 不归零制
      3. 曼彻斯特编码:特点:本身具备同步信号
      4. 差分曼彻斯特编码
    
  • 信道复用技术:

    1. 频分复用(FDM):所用用户在同样时间占用不同的带宽资源
    2. 时分复用(TDM):所用用户在不同时间内占用相同的频带宽度
    3. 统计时分复用(STDM):时分复用的改进,提高了信道的利用率
    4. 波分复用(WDM):光纤中使用的,相当于光的频分复用
    5. 码分复用(CDM):每一个用户可以在同样的时间使用同样的频带进行通信,由于各用户使用经过特殊挑选的不同码型,各用户之间不会干扰
  • 最基本的三种调制方法:调幅、调频、调相

(3)数据链路层

PPP协议:一对一、点对点通信协议,被用于点对点信道
CSMA/CD协议:载波监听多点接入/碰撞检测协议,被用于一对多的广播信道

位于此层的设备:

  1. 适配器(即网卡)

    位于:数据链路层与物理层
    功能: (1)进行数据串并行转换
    	   (2)缓存数据
    	   (3)安卓设备驱动程序
    
  2. 集线器

     位于:物理层
     功能:多接口转发器,只简单转发原比特
     集线器机器带宽=集线器带宽/机器数
    
  3. 交换机

     位于:数据链路层
     功能:多接口网桥
     	  并行全双工通信,独占传输媒体,无碰撞地传输数据
    

(4)网络层

IP协议
ARP地址解析协议:将ip地址通过ARP解析成硬件MAC地址协议
ICMP网际控制报文协议:将IP数据报加上数据报首部发送出去的协议
RIP内部网关协议:按固定时间间隔与相邻路由器交换路由信息的路由选择协议

设备:
路由器:一种具有多个输入输出端口,用于转发分组的专用计算机

  • ip地址
    ip地址是计算机在互联网中的唯一的32位标识符

    • ip地址主要由网络号和主机号组成,网络号也称为网络前缀、网络标识,用来确定拥有该IP地址的主机位于哪个网络,主机号用于确定主机属于该网络的哪一台主机。

      在这里插入图片描述
      本地iP地址为:127.0.0.1,通常可以ping此地址测试本地TCP/IP协议

    • 为了提高利用率,进行了子网划分,如今,一个ip地址被划分为三个部分,网络号,子网号,主机号

        子网掩码:
        	A类:255.0.0.0
        	B类: 255.255.0.0
        	C类:255.255.255.0
      

      根据网络地址是否相同可以判定两个ip地址是否在一个子网上:
      网络地址 = ip地址 AND(逐位相与) 子网掩码

    • IPV6

      随着网络的发展,IPV4的网络地址资源不足,于是引入IPV6来解决此问题,IPv6的地址长度为128位,是IPv4地址长度的4倍。格式为X:X:X:X:X:X:X:X,其中每个X表示地址中的16b,以十六进制表示,例如:

      ABCD:EF01:2345:6789:ABCD:EF01:2345:6789


(5)运输层

TCP/IP协议:在多个不同网络间实现信息传输的协议簇。TCP/IP协议不仅仅指的是TCP 和IP两个协议,而是指一个由FTP、SMTP、TCP、UDP、IP等协议构成的协议簇。

TCP协议:传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议

  • TCP建立连接:三次握手

    即建立一个TCP连接时,需要客户端和服务器总共发送3个包。进行三次握手的主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备。

     1.首先客户端向服务器端发起连接请求
     2.服务器端向客户端回应,已收到客户端的连接请求,同时向客户端发起连接,包含一个确认报文和一个同步报文
     3.客户端向服务器端回应,已收到服务器端的连接请求
    

    在这里插入图片描述

TCP之间的连接,由通信两端的两个端点(即套接字socket)所确定

连接建立,接下来即可进行通信

  • TCP断开连接,四次挥手

    由于TCP的半关闭,即TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。TCP 连接的拆除需要发送四个包,因此称为四次挥手(Four-way handshake),客户端或服务端均可主动发起挥手动作。

     1.首先客户端向服务器端发起断开连接请求
     2.服务器端向客户端回应,允许客户端断开,此时客户端——>服务器方向连接关闭
     3.服务器端向客户端发起断开连接请求
     4.客户端向服务器端回应,允许服务器断开,此时此时服务器端——>客户端方向连接关闭
    

    在这里插入图片描述

  • 拥塞控制:慢开始、拥塞避免、快重传、快恢复

      慢开始:每经过一个传输轮次,拥塞窗口cwnd就加倍
      拥塞避免:当拥塞窗口cwnd>慢开始门限ssthresh,每经过一个传输轮次,cwnd+1
      快重传:适用于个别报文丢失情况,即一连收到3个重复确认
      快恢复:快重传后执行,ssthresh=cwnd/2,cwnd=ssthresh,开始执行拥塞避免
    

在这里插入图片描述

UDP协议:用户数据报协议,是一个简单的面向数据报的运输层协议。是一种无连接、不可靠、快速传输、面向数据报的传输层通信协议,只是把应用程序传给IP层的数据报发送出去,但是不能保证它们能到达目的地。

(6)应用层

HTTP协议:超文本传输协议,负责 web 服务器与 web 浏览器之间的通信,用于从 web 客户端向 web 服务器发送请求,并从 web 服务器向 web 客户端返回内容。

HTTP请求/响应的步骤
  1. 客户端连接到Web服务器

     客户端与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接
    
  2. 发送HTTP请求

    通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,
    一个请求报文由请求行、请求头部、空行和请求数据4部分组成。
    
  3. 服务器接受请求并返回HTTP响应

     Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。
     一个响应由状态行、响应头部、空行和响应数据4部分组成。
    
  4. 释放TCP连接

    - HTTP/1.0中默认使用短连接,客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。
    
    - 而从HTTP/1.1起,默认使用长连接,,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。
    使用长连接,会在响应头加入:Connection:keep-alive
    
  5. 客户端浏览器解析HTML内容

    客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。
    
    HTTP返回码:
    1XX(信息状态码)接受请求正在处理
    2XX(成功状态码) 请求正常处理完毕
    3XX(重定向状态码) 需要附加操作已完成请求
    4XX(客户端错误状态码) 服务器无法处理请求
    5XX(服务器错误状态码) 服务器处理请求出错
    
    解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。
    

在浏览器地址栏键入URL,按下回车之后会经历以下流程:

1. 浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;
2. 解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器建立TCP连接;
3. 浏览器发出读取文件(URL 中域名后面部分对应的文件)的HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器;
4. 服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器;
5. 浏览器将该 html 文本并显示内容;  
HTTP请求方式
  • GET

      向指定的资源发出“显示”请求。
      使用GET方法应该只用在读取数据,而不应当被用于产生“副作用”的操作中,
      例如在Web Application中。其中一个原因是GET可能会被网络蜘蛛等随意访问。
    
  • POST

      向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。
      数据被包含在请求本文中。
      这个请求可能会创建新的资源或修改现有资源,或二者皆有。
    
  • PUT

      向指定资源位置上传其最新内容。
    
  • DELETE

      请求服务器删除Request-URI所标识的资源。
    



HTTPS协议:安全的HTTP协议,在其基础上,增加了SSL协议,即安全套接字层,实现安全数据传输

FTP协议:文件传输协议,负责计算机之间的文件传输

SMTP协议:简易邮件传输协议,用于电子邮件的传输



2.TCP协议C/S结构常用相关类

java.net.ServerSocket

介绍:搭建服务器主要的实现类,实现服务器套接字。 服务器套接字等待通过网络进入的请求。 它根据该请求执行某些操作,然后可能将结果返回给请求者。

构造方法描述
ServerSocket()创建未绑定端口的服务器套接字。
ServerSocket​(int port)创建绑定到指定端口的服务器套接字。

常用方法:

修饰方法名描述
Socketaccept()等待套接字的连接,直到连接后继续运行,返回一个连接成功的可操作socket对象
voidclose()关闭此套接字。
InetAddressgetInetAddress()返回此服务器套接字的本地地址。
intgetLocalPort()返回此套接字绑的端口号。

java.net.Socket

介绍:客户端套接字的实现类。两台计算机可通过ip地址和端口通过套接字通信

构造方法描述
Socket()创建一个未连接的套接字,系统默认类型为SocketImpl。
Socket​(String host, int port)创建一个指定ip地址和端口的套接字
Socket​(InetAddress address, int port)创建一个指定InetAddress对象和端口的套接字

常用方法:

修饰方法名描述
InetAddressgetInetAddress()返回套接字连接的InetAddress对象
InputStreamgetInputStream()返回此套接字的字节输入流。
OutputStreamgetOutputStream()返回此套接字的字节输出流。
intgetPort()返回此套接字连接的远程端口号
voidclose()关闭此套接字。

C/S结构项目实例练习

要求:创建可通信的客户端和服务器端,要求服务器可多线程接收客户端连接,注意服务器端与客户端的输入输出流交替顺序建立

服务器端:

/*服务器端*/
public class Service {
    public static void main(String[] args) throws IOException {
        //搭建服务器
        ServerSocket serverSocket = new ServerSocket(4241);
        //等待客户端连接
        System.out.println("服务器已搭建");
        while(true){
            //连接socket
            Socket socket = serverSocket.accept();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        //客户端先发送数据,服务器端接收数据
                        InputStream inputStream = socket.getInputStream();
                        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                        System.out.println("服务器接收到的数据为:" + bufferedReader.readLine());
                        //然后服务器端发送数据,客户端接收数据
                        OutputStream outputStream = socket.getOutputStream();
                        outputStream.write("这是服务器的一条信息\n".getBytes());//注意添加换行
                        System.out.println("服务器发送的数据为:" + "这是服务器的一条信息");
                        inputStream.close();
                        outputStream.close();
                        socket.close();
                        System.out.println("服务器端工作完毕,关闭");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }
            }).start();
            System.out.println("一个客户端已连接");
        }
    }
}

客户端:

/*客户端 */
public class Test {
    public static void main(String[] args) throws IOException {
        //客户端连接服务器
        Socket socket = new Socket("127.0.0.1",4241);
        //客户端先发送数据,服务器端接收数据
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("这是客户端的一条信息\n".getBytes());//注意添加换行
        System.out.println("客户端发送的数据为:" + "这是客户端的一条信息");
        
        //然后服务器端发送数据,客户端接收数据
        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        System.out.println("客户端接收到的数据为:" + bufferedReader.readLine());
        
        //关闭
        inputStream.close();
        outputStream.close();
        socket.close();
        System.out.println("客户端工作完毕,关闭");
        
    }
}

实例操作结果

1.打开服务器端,运行到accept()处,等待socket连接后开启新线程后继续运行
在这里插入图片描述
2.打开客户端,客户端和服务器端正式开启通信,可以互相发送各种类型数据

在这里插入图片描述
在这里插入图片描述

可能出现的问题:

1.在使用BufferReader字符缓冲输入流进行服务器和客户端交互时,使用readLine()读取数据可能会发生阻塞,原因是因为readLine()只有在读取到'\n','\r'时才会停止
解决方式:在传输数据时,在字符数据的结尾,添加'\n','\r'



3.描述IP地址类——InetAddress

java.net.InetAddress

介绍:此类的IP地址的操作类,可以通过静态方法获取ip地址的相关属性,且拥有两个子类分别对应IPV4和IPV6

获取对象的方式:根据主机名调用静态方法传递ip地址

InetAddress ip = InetAddress.getByName("192.168.102.228");

常用方法:

修饰方法名描述
static InetAddressgetByName​(String host)传入一个主机ip获取InetAddress对象
StringgetHostAddress()返回此对象所绑定的ip地址
staticInetAddress getLocalHost()返回本地主机的ip地址,相当于localhost



4.网址操作类相关类

java.net.URL

介绍:URL表示统一资源定位符。 资源可以是文件或目录这样简单的东西,也可以是对更复杂的对象的引用,例如对数据库或搜索引擎的查询。这个类可以对这些资源建立一个可操作的对象进行处理。

URL的组成:

protocol://host:port/path?query#fragment
  • protocol(协议)
    指定使用的传输协议,下表列出 protocol 属性的有效方案名称。 最常用的是HTTP协议
  • hostname(主机名)
    指存放资源的服务器的域名系统(DNS) 主机名或 IP 地址。
  • port(端口号)
    省略时使用方案的默认端口,各种传输协议都有默认的端口号
  • path(路径)
    由零或多个“/”符号隔开的字符串,一般用来表示主机上的一个目录或文件地址。
  • parameters(参数)
    用于指定特殊参数的可选项。
  • query(查询)
    用于给动态网页(如使用CGI、ISAPI、PHP/JSP/ASP/ASP.NET等技术制作的网页)传递参数
  • fragment(信息片断)
    用于指定网络资源中的片断
构造方法描述
URL​(String spec)传入一个字符串网址建立URL对象
URL​(String protocol, String host, int port, String file)创建 URL从指定对象 protocol , host , port号和 file 。

常用方法:

修饰方法名描述
StringgetFile()获取此 URL的文件名。
StringgetHost()获取此 URL的主机名(如果适用)。
StringgetPath()获取此 URL的路径部分。
intgetPort()获取此 URL的端口号。
StringgetProtocol()获取此 URL的协议名称。
StringgetQuery()获取此 URL的查询部分。
URItoURI()返回与此URL等效的URI 。
URLConnectionopenConnection()返回一个连接此URL对象的URLConnection对象

实例:

   		//创建一个网址对象(统一资源定位符)
        URL url = new URL("");
        //打开链接 , 并得到链接对象
        URLConnection conn = url.openConnection();
        //通过连接对象, 获取连接到的文件的输入流
        InputStream is = conn.getInputStream();
        //接下来就可以对IO流数据进行操作了

java.net.URLConnection

介绍: 表示程序与URL连接的父类,可读取和写入URL的资源

构造方法描述
protectedURLConnection​(URL url) 构造指向指定URL的URL连接。

常用方法:

修饰方法名描述
booleangetDoInput()设置此URL连接是否可以进行输入,不可以则置为flase,默认是true
booleangetDoOutput()设置此URL连接是否可以进行输出,不可以则置为flase,默认是true
InputStreamgetInputStream()返回从此打开的连接读取的输入流。
OutputStreamgetOutputStream()返回写入此连接的输出流。
URLgetURL()返回此 URLConnection的 URL字段的值。

java.net.HttpURLConnection

介绍:URLConnection类的子类,适用于使用HTTP或HTTPS网络协议

构造方法描述
protectedHttpURLConnection​(URL u) HttpURLConnection的构造函数。

常用方法:

修饰方法名描述
voidsetRequestMethod​(String method)设置 URL 请求的方法,它是 HTTP 方法 GET,POST,HEAD,OPTIONS,PUT,DELETE 和 TRACE之一。默认方法是 GET(注意:这里方法类型必须大写)。

URL下载练习实例练习

要求,能够将网络资源文件下载到本地

public class Test {

        public static void main(String[] args) throws Exception {
            Scanner input = new Scanner(System.in);
            System.out.println("请输入要下载的文件网址:");
            String urlString = input.nextLine();
            System.out.println("请输入要保存的文件名称:");
            System.out.println("(文件默认下载位置:D盘download文件夹中)");
            String fileString = input.nextLine();
            //1.    确保文件夹存在
            File dir = new File("D:\\download");
            if(!dir.exists()) {
                dir.mkdirs();
            }
            //2.    创建一个文件输出流, 用于输出数据
            FileOutputStream fos = new FileOutputStream(new File(dir,fileString));
            //3.1   创建一个网址对象(统一资源定位符)
            URL url = new URL(urlString);
            //3.2   打开链接 , 并得到链接对象
            URLConnection conn = url.openConnection();
            //3.3   通过连接对象, 获取连接到的文件的输入流
            InputStream is = conn.getInputStream();
            //3.4   循环读取 并写出到fos中
            //用于存储 每次读取的数据
            byte[] bytes = new byte[1024*1024];
            //用于存储每次读取的数据长度
            int len = -1;
            //用于存储已读取的所有数据的长度
            int count = 0;
            while((len = is.read(bytes))!=-1) {
                //将每次循环读取的bytes  写出到文件中
                fos.write(bytes,0,len);
                count+=len;
            }
            is.close();
            System.out.println("文件下载完毕");
        }
}


提供一些直接下载文件资源的URL链接:

http://wx.zemuo.com/paper/award/img.php?txt1=txt1-2&txt2=张三
参数解释:
    txt1=text-数字   中的数字表示奖状类型。
    
http://wx.zemuo.com/paper/news/msld/img.php?id=2&txt1=王二狗

http://wx.zemuo.com/app/ali3m/img.php?txt1=下午18:22&txt2=中国移动&txt3=12&txt4=0.00001

5.中文转码解码

在实际开发中,直接以中文进行数据传输可能会出现问题,于是,通常都是将中文转码进行传输,然后到达后进行解码

java.net.URLEncoder

介绍:非URL的子类,此类用于将string转化为application/x-www-form-urlencoded MIME格式

修饰方法名描述
static Stringencode​(String s, String enc)使用特定编码方案将字符串转换为 application/x-www-form-urlencoded格式。

java.net.URLDecoder

介绍:非URL的子类,此类用于解码application/x-www-form-urlencoded MIME格式成String

修饰方法名描述
static Stringdecode​(String s, String enc)使用特定编码方案解码 application/x-www-form-urlencoded字符串

中文转码解码实例

//字符串中的非西欧字符的内容,会被转化成%XX%XX XX 为十六进制的数字
String urlString = URLEncoder.encode("你好", "UTF-8");
System.out.println(urlString);//输出:%E4%BD%A0%E5%A5%BD
String keyWord = URLDecoder.decode("%E4%BD%A0%E5%A5%BD", "UTF-8");
System.out.println(keyWord);//输出:你好



6.IDEA常用快捷键

  • 提示与代码生成部分

Alt + Enter IDEA 根据光标所在问题,提供快速修复选择

Ctrl + Alt + T 对选中的代码弹出环绕选项弹出层(try,if等语句包裹)

Alt + Insert 代码自动生成,如生成对象的 set / get 方法,构造函数,toString() 等

Ctrl + O 选择可重写的方法

Ctrl + I 选择可实现的方法

Ctrl + / 注释光标所在行代码,会根据当前不同文件类型使用不同的注释符号

  • 选择/移动/复制代码:

Ctrl + W递进式选择代码块

ctrl+Shift+w 递进式取消选择代码块

Ctrl + D 复制光标所在行 或 复制选择内容,并把复制内容插入光标位置下面

Ctrl+Shift+↑或↓ : 移动当前行或代码结构

Ctrl + Y 删除光标所在行 或 删除选中的行

Ctrl + X 剪切光标所在行 或 剪切选择内容

  • 代码优化

Ctrl + Alt + O 优化导入的类,可以对当前文件和整个包目录使用

Ctrl + Alt + L 格式化代码,可以对当前文件和整个包目录使用

  • 查找与替换

Ctrl + F 在当前文件进行文本查找
Ctrl + Shift + F 根据输入内容查找整个项目 或 指定目录内文件

Ctrl + R 在当前文件进行文本替换
Ctrl + Shift + R 根据输入内容替换对应内容,范围为整个项目 或 指定目录内文件

  • 阅读代码部分

Ctrl + F12 弹出当前文件结构层(类的方法属性等),可以在弹出的层上直接输入,进行筛选

Ctrl + Q 光标所在的变量 / 类名 / 方法名等上面(也可以在提示补充的时候按),显示文档内容



都学习到这里了。不如关注一波呗~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南窗木心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值