Java学习总结(2021版)---网络编程基础

一:概述

  • 网络编程的目的: 直接或间接地通过网络协议与其它计算机实现数据交换,进行通讯

  • 实现网络通信需要解决的两个问题:

    • 如何准确地定位网络上一台或多台主机;定位主机上的特定的应用
    • 找到主机后如何可靠高效地进行数据传输

二:网络通讯要素

  • 解决问题一:IP和端口号
  • 解决问题二:提供网络通信协议:TCP/IP参考模型(应用层、传输层、网络层、物理+数据链路层)

通讯要素一:IP和端口号

IP的理解

  • IP:唯一的标识 Internet 上的计算机(通信实体)
  • 在Java中使用InetAddress类代表IP
  • IP分类
    • 方式1:IPv4 和 IPv6
    • 方式2:公网地址( 万维网使用)和 私有地址( 局域网使用)
  • 域名: 通过域名解析服务器将域名解析为IP地址 www.baidu.com www.mi.com www.jd.com
  • 域名解析:域名容易记忆,当在连接网络时输入一个主机的域名后,域名服务器(DNS)负责将域名转化成IP地址,这样才能和主机建立连接。
  • 本地回环地址(hostAddress):127.0.0.1 主机名(hostName):localhost
  • Internet上的主机有两种方式表示地址:
    • 域名(hostName):www.baidu.com
    • IP 地址(hostAddress):202.108.35.210

端口号:
在这里插入图片描述

InetAddress类
在这里插入图片描述

  • 域名容易记忆,当在连接网络时输入一个主机的域名后,域名服务器(DNS)
    负责将域名转化成IP地址,这样才能和主机建立连接。 -------域名解析

在这里插入图片描述

  • 常用的方法

在这里插入图片描述
代码实例:

public static void main(String[] args) {
    
    
    try {
    
    
        //通过域名来获得InetAddress实例
        InetAddress inet2 = InetAddress.getByName("www.baidu.com");
        System.out.println(inet2);//www.baidu.com/39.156.66.18
     
        //通过ip来获得InetAddress实例
        InetAddress inet3 = InetAddress.getByName("127.0.0.1");
        System.out.println(inet3);//127.0.0.1
     
        //获取本地InetAddress实例
        InetAddress inet4 = InetAddress.getLocalHost();
        System.out.println(inet4);//DESKTOP-EV2S7MJ/10.1.1.127

        //getHostAddress()获取主机域名
        System.out.println(inet2.getHostName());//www.baidu.com
        //getHostAddress();获取主机的ip地址
        System.out.println(inet2.getHostAddress());//39.156.66.14
    } catch (UnknownHostException e) {
    
    
        e.printStackTrace();
    }
}

通信要素二:网络通信协议

TCP协议 和 UDP协议

在这里插入图片描述

  • 三次握手:确保通信对方在线
  • 四次握手:确保连接断开

Socket
在这里插入图片描述

  • Socket类的常用构造器:

    • public Socket(InetAddress address,int port)创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
    • public Socket(String host,int port)创建一个流套接字并将其连接到指定主机上的指定端口号。
  • Socket类的常用方法:

在这里插入图片描述

三:TCP网络编程

1:简述

Java语言的基于套接字Socket编程,分为客户端和服务端

2:客户端Socket的工作过程包含以下四个基本的步骤:

在这里插入图片描述

  • 注意:客户端程序可以使用Socket类创建对象,创建的同时会自动向服务器方发起连

3:服务器程序的工作过程包含以下四个基本的步骤:
在这里插入图片描述
4:举例:

在这里插入图片描述

代码实例1:----- 客户端发送信息给服务端,服务端将数据显示在控制台上

import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Objects;

/**
 * 实现TCP的网络编程
 * 例子1:客户端发送信息给服务端,服务端将数据显示在控制台上
 */
public class TCPTest1 {
    
    

    //客户端
    @Test
    public void client()  {
    
    
        Socket socket = null;
        OutputStream os = null;
        try {
    
    
            //1.创建Socket对象,指明服务器端的ip和端口号
            InetAddress inet = InetAddress.getByName("192.168.14.100");//获取此IP地址的主机名
            socket = new Socket(inet,8899);
            //2.获取一个输出流,用于发送数据给服务器
            os = socket.getOutputStream();
            //3.写出数据的操作
            os.write("你好,我是客户端mm".getBytes());
            
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            //4.资源的关闭
            if(os != null){
    
    
                try {
    
    
                    os.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
            if(socket != null){
    
    
                try {
    
    
                    socket.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
        }



    }
    //服务端
    @Test
    public void server()  {
    
    

        ServerSocket ss = null;
        Socket socket = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
    
    
            //1.创建服务器端的ServerSocket,指明自己的端口号
            ss = new ServerSocket(8899);
            //2.调用accept()表示接收来自于客户端的socket(监听一个客户端的连接)
            //该方法是一个阻塞方法,如果没有客户端连接将一直等待
            socket = ss.accept();
            //3.获取输入流,用来接收客户端发送的数据
            is = socket.getInputStream();

            //不建议这样写,可能会有乱码
//        byte[] buffer = new byte[1024];因为此处长度如果小于接受数据的长度,导致分成两半,后续用String接收会乱码
//        int len;
//        while((len = is.read(buffer)) != -1){
    
    
//            String str = new String(buffer,0,len);
//            System.out.print(str);
//        }
            
            //4.读取输入流中的数据
            //因为此处如果小于接收的数据长度,并不会单独还原成字符串,而是先拼起来整体再还原
            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[5];
            int len;
            while((len = is.read(buffer)) != -1){
    
    
            	/**ByteArrayOutputStream源码
            	 * public synchronized void write(byte b[], int off, int len) {
        				Objects.checkFromIndexSize(off, len, b.length);
        				ensureCapacity(count + len);
        				System.arraycopy(b, off, buf, count, len);
        				count += len;
    				}
            	 */
            	//把数据写到baos对象,以便后续整体还原
                baos.write(buffer,0,len);
            }
            /**ByteArrayOutputStream源码
             * protected byte buf[];
             */
            
            /**
             * public synchronized String toString() {
        		return new String(buf, 0, count);
    		}
             */
            		//把内部字节字符直接转换成字符串
            System.out.println(baos.toString());

            System.out.println("收到了来自于:" + socket.getInetAddress().getHostAddress() + "的数据");

        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if(baos != null){
    
    
                //5.关闭资源
                try {
    
    
                    baos.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
            if(is != null){
    
    
                try {
    
    
                    is.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
            if(socket != null){
    
    
                try {
    
    
                    socket.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
            if(ss != null){
    
    
                try {
    
    
                    ss.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }

        }





    }

}

代码实例2:----- 从客户端发送文件给服务端,服务端保存到本地。并返回“发送成功”给客户端


/*
    这里涉及到的异常,应该使用try-catch-finally处理
     */

public class TCPTest3 {
    
    
    @Test//客户端
    public void client() throws Exception{
    
    
        //创建Socket对象,指明服务器端的ip和端口号
        InetAddress inet = InetAddress.getByName("127.0.0.1");
        Socket socket = new Socket(inet,9090);
      
        //获取输出流,用来发送数据给服务器
        OutputStream so = socket.getOutputStream();
        FileInputStream fis = new FileInputStream(new File("one.jpg"));
        byte[] buffer = new byte[1024];
        int len;
        //将从文件中读取的数据发送给服务器
        while((len = fis.read(buffer)) != -1){
    
    
            so.write(buffer,0,len);
        }
        //关闭数据的输出,会在流末尾写入一个“流的末尾”的标记,服务器才能读到-1,否则对方的读取会一直阻塞
        socket.shutdownOutput();
      
        //接收来自服务器端的数据,并显示到控制台上
        InputStream is = socket.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        System.out.println("我想接收来自服务器的数据");
        while((len = is.read(buffer)) != -1){
    
    
            baos.write(buffer,0,len);
        }
        System.out.println(baos.toString());
        //关闭流
        baos.close();
        is.close();
        fis.close();
        so.close();
        socket.close();
    }

    @Test//服务器
    public void server() throws Exception{
    
    
        ServerSocket ss = new ServerSocket(9090);
        Socket socket = ss.accept();
        InputStream is = socket.getInputStream();
        FileOutputStream fos = new FileOutputStream(new File("three.jpg"));
        byte[] buffer = new byte[1024];
        int len;
        while((len = is.read(buffer)) != -1){
    
    
            fos.write(buffer,0,len);
        }
        //服务器端给与客户端反馈
        OutputStream os = socket.getOutputStream();
        os.write("你好,文件我已经收到".getBytes());
        //关闭流
        os.close();
        fos.close();
        is.close();
        socket.close();
        ss.close();
    }
}

四:UDP网络编程(了解)

五:URL编程------它表示 Internet 上某一资源的地址

在这里插入图片描述

概述:
在这里插入图片描述
URL的基本结构由5部分组成:
在这里插入图片描述
URL类常用方法:

在这里插入图片描述
代码示例:

public class URLTest {
    
    

    public static void main(String[] args) {
    
    

        try {
    
    

            URL url = new URL("http://localhost:8080/examples/beauty.jpg?username=Tom");

//            public String getProtocol(  )     获取该URL的协议名
            System.out.println(url.getProtocol());
//            public String getHost(  )           获取该URL的主机名
            System.out.println(url.getHost());
//            public String getPort(  )            获取该URL的端口号
            System.out.println(url.getPort());
//            public String getPath(  )           获取该URL的文件路径
            System.out.println(url.getPath());
//            public String getFile(  )             获取该URL的文件名
            System.out.println(url.getFile());
//            public String getQuery(   )        获取该URL的查询名
            System.out.println(url.getQuery());




        } catch (MalformedURLException e) {
    
    
            e.printStackTrace();
        }

    }


}

猜你喜欢

转载自blog.csdn.net/m0_51755061/article/details/114269658