Java网络编程

要想实现网络通信,需要解决的三个问题:

  • 问题1:如何准确确定定位网络上一台或多台主机

  • 问题2:如何定位主机上的特定的应用

  • 问题3:找到主机后,如何可靠、高效地进行数据传输

实现网络传输的三个要素:(对应解决三个问题)

> 使用IP地址(准确确定定位网络上一台或多台主机)

> 使用端口号(定位主机上的特定的应用)

> 规范网络通信协议(可靠、高效地进行数据传输)

通信要素1:IP地址

IP地址用来给网络中的一台计算机设备做唯一的编号

IP地址分类

> IP地址分类方式1

IPv4(占用4个字节)

IPv6(占用16个字节)

> IP地址分类方式2
公网地址(万维网使用)和 私有地址(局域网使用。以192.168开头)

本地回路地址

127.0.0.1(回环自检)

域名

便捷的记录ip地址,ip地址与域名一一对应

www.baidu.com www.atguigu.com www.bilibili.com

www.jd.com www.mi.com www.vip.com

端口号

> 可以唯一标识主机中的进程(应用程序)

> 不同的进程分配不同的端口号

> 范围:0~65535(两个字节)

通信协议

网络通信协议的目的

为了实现可靠而高效的数据传输。

网络参考模型

OSI参考模型:将网络分为7层,过于理想化,没有实施起来。

TCP/IP参考模型:将网络分为4层:应用层、传输层、网络层、物理+数据链路层。事实上使用的标准。

TCP: 可靠的连接(发送数据前,需要三次握手、四次挥手),进行大数据量的传输,效率低。

UDP: 不可靠的连接(发送前,不需要确认对方是否在)、使用数据报传输(限制在64kb以内)、效率高。

InetAddress的使用

作用

InetAddress类的一个实例就代表一个具体的ip地址。

实例化方式

InetAddress getByName(String host):获取指定ip对应的InetAddress的实例

InetAddress getLocalHost():获取本地ip对应的InetAddress的实例

常用方法

getHostName():获取域名,如果没有就获取ip地址

getHostAddress():获取ip地址

TCP

java 复制代码
import java.net.InetAddress;
import java.net.UnknownHostException;

public class Main {
    public static void main(String[] args) {
        try {
            //1. 实例化
            //getByName(String host): 获取指定ip对应的InetAddress的实例
            InetAddress inet1 = InetAddress.getByName("192.168.23.31");
            System.out.println(inet1);

            InetAddress inet2 = InetAddress.getByName("www.atguigu.com");
            System.out.println(inet2); //www.atguigu.com/122.228.95.175

            //getLocalHost(): 获取本地ip对应的InetAddress的实例
            InetAddress inet3 = InetAddress.getLocalHost();
            System.out.println(inet3); //DESKTOP-QCP2QPI/192.168.21.107

            InetAddress inet4 = InetAddress.getByName("127.0.0.1");
            System.out.println(inet4);

            //2. 两个常用的方法
            System.out.println(inet1.getHostName()); //192.168.23.31
            System.out.println(inet1.getHostAddress()); //192.168.23.31

            System.out.println(inet2.getHostName()); //www.atguigu.com
            System.out.println(inet2.getHostAddress()); //122.228.95.175
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}

UDP

java 复制代码
public void sender() throws Exception {
        //1. 创建DatagramSocket的实例
        DatagramSocket ds = new DatagramSocket();

        //2. 将数据、目的地的ip、目的地的端口号都封装在DatagramPacket数据报中
        InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
        int port = 9090;
        byte[] bytes = "我是发送端".getBytes("utf-8");
        DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length, inetAddress, port);

        //3. 发送数据
        ds.send(packet);

        ds.close();
    }

    public void receiver() throws Exception {
        //1. 创建DatagramSocket的实例
        int port = 9090;
        DatagramSocket ds = new DatagramSocket(port);

        //2. 创建数据报的对象,用于接收发送端发送过来的数据
        byte[] buffer = new byte[1024 * 64];
        DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);

        //3. 接收数据
        ds.receive(packet);

        //4. 获取数据,并打印到控制台上
        String str = new String(packet.getData(), 0, packet.getLength());
        System.out.println(str);

        ds.close();
    }

URL(Uniform Resource Locator)

统一资源定位符 (种子)

作用

一个具体的url就对应着互联网上某一资源的地址。

URL的格式:

http://192.168.21.107:8080/example/abcd.jpg?name=Tom ---> "万事万物皆对象"

应用层协议 ip地址 端口号 资源地址 参数列表

URL类的实例化及常用方法

  • public String getProtocol() 获取该URL的协议名

  • public String getHost() 获取该URL的主机名

  • public String getPort() 获取该URL的端口号

  • public String getPath() 获取该URL的文件路径

  • public String getFile() 获取该URL的文件名

  • public String getQuery() 获取该URL的查询名

java 复制代码
import java.net.URL;

public class Main {
    public static void main(String[] args) {
        String str = "http://192.168.21.107:8080/examples/abcd.jpg?name=Tom";

        try {
            URL url = new URL(str);

            /*
            * - public String getProtocol() 获取该URL的协议名
            - public String getHost() 获取该URL的主机名
            - public String getPort() 获取该URL的端口号
            - public String getPath() 获取该URL的文件路径
            - public String getFile() 获取该URL的文件名
            - public String getQuery() 获取该URL的查询名
            */

            System.out.println(url.getProtocol());
            System.out.println(url.getHost());
            System.out.println(url.getPort());
            System.out.println(url.getPath());
            System.out.println(url.getFile());
            System.out.println(url.getQuery());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

下载指定的URL的资源到本地

java 复制代码
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class Main {
    public static void main(String[] args) throws IOException {
        // 1、获取URL实例
        URL url = new URL("http://127.0.0.1:8080/examples/abcd.jpg");
        // 2、建立与服务器的链接
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        // 3、获取输入流、创建输出流
        InputStream is = urlConnection.getInputStream();
        File file = new File("dest.jpg");
        FileOutputStream fos = new FileOutputStream(file);
        // 4、读写数据
        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer)) != -1) {
            fos.write(buffer, 0, len);
        }
        System.out.println("文件下载成功");

        // 5、关闭资源
        fos.close();
        is.close();
        urlConnection.disconnect();
    }
}

练习

客户端发送内容给服务端,服务端将内容打印到控制台上。

java 复制代码
public void client() {
        Socket socket = null;
        OutputStream os = null;
        try {
            // 1、创建一个Socket
            InetAddress inetAddress = InetAddress.getByName("192.168.21.107"); //声明对方的ip地址
            int port = 8989; //声明对方的端口号
            socket = new Socket(inetAddress, port);

            // 2、发送数据
            os = socket.getOutputStream();
            os.write("你好,我是客户端,请多多关照".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 3、关闭socket、关闭流
            try {
                if (os != null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (os != null)
                    os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void server() {
        ServerSocket serverSocket = null;
        Socket socket = null; //阻塞式的方法
        InputStream is = null;
        try {
            // 1、创建一个ServerSocket
            int port = 8989;
            serverSocket = new ServerSocket(port);

            // 2、调用accept(),接收客户端的Socket
            socket = serverSocket.accept();
            System.out.println("服务器端已开启");

            System.out.println("收到了来自于" + socket.getInetAddress().getHostAddress() + "的连接");

            //3. 接收数据
            is = socket.getInputStream();
            byte[] buffer = new byte[5];
            int len;
            ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 内部维护了一个byte[]
            while ((len = is.read(buffer)) != -1) {
                // 错误的,可能会出现乱码。
//                String str = new String(buffer, 0, len);
//                System.out.print(str);

                // 正确的
                baos.write(buffer, 0, len);
            }

            System.out.println(baos.toString());

            System.out.println("\n数据接收完毕");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 4、关闭Socket、ServerSocket、流
            try {
                if (socket != null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (serverSocket != null)
                    serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (is != null)
                    is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

客户端发送文件给服务端,服务端将文件保存在本地。

java 复制代码
public void client() {
        Socket socket = null;
        FileInputStream fis = null;
        OutputStream os = null;
        try {
            // 1. 创建Socket
            // 指明对方(即为服务器端)的ip地址和端口号
            InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
            int port = 9090;
            socket = new Socket(inetAddress, port);

            // 2. 创建File的实例、FileInputStream的实例
            File file = new File("pic.jpg");
            fis = new FileInputStream(file);
            // 3. 通过Socket,获取输出流
            os = socket.getOutputStream();

            // 4. 读写数据
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }

            System.out.println("数据发送完毕");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 5. 关闭Socket和相关的流
            try {
                if (os != null)
                    os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fis != null)
                    fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (socket != null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void server() {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            //1. 创建ServerSocket
            int port = 9090;
            serverSocket = new ServerSocket(port);

            //2. 接收来自于客户端的socket:accept()
            socket = serverSocket.accept();

            //3. 通过Socket获取一个输入流
            is = socket.getInputStream();

            //4. 创建File类的实例、FileOutputStream的实例
            File file = new File("pic_copy.jpg");
            fos = new FileOutputStream(file);

            //5. 读写过程
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }

            System.out.println("数据接收完毕");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //6. 关闭相关的Socket和流
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (is != null)
                    is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (socket != null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (serverSocket != null)
                    serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

从客户端发送文件给服务端,服务端保存到本地。并返回"发送成功"给客户端。并关闭相应的连接。

java 复制代码
public void client() {
        Socket socket = null;
        FileInputStream fis = null;
        OutputStream os = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
            // 1. 创建Socket
            // 指明对方(即为服务器端)的ip地址和端口号
            InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
            int port = 9090;
            socket = new Socket(inetAddress, port);

            // 2. 创建File的实例、FileInputStream的实例
            File file = new File("pic.jpg");
            fis = new FileInputStream(file);
            // 3. 通过Socket,获取输出流
            os = socket.getOutputStream();

            // 4. 读写数据
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }

            System.out.println("数据发送完毕");

            // 客户端表明不再继续发送数据
            socket.shutdownOutput();

            //5. 接收来自于服务器端的数据
            is = socket.getInputStream();
            baos = new ByteArrayOutputStream();
            byte[] buffer1 = new byte[5];
            int len1;
            while ((len1 = is.read(buffer1)) != -1) {
                baos.write(buffer, 0, len1);
            }
            System.out.println(baos.toString());

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 6. 关闭Socket和相关的流
            try {
                baos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (os != null)
                    os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fis != null)
                    fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (socket != null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void server() {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is = null;
        FileOutputStream fos = null;
        OutputStream os = null;
        try {
            //1. 创建ServerSocket
            int port = 9090;
            serverSocket = new ServerSocket(port);

            //2. 接收来自于客户端的socket:accept()
            socket = serverSocket.accept();

            //3. 通过Socket获取一个输入流
            is = socket.getInputStream();

            //4. 创建File类的实例、FileOutputStream的实例
            File file = new File("pic_copy.jpg");
            fos = new FileOutputStream(file);

            //5. 读写过程
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }

            System.out.println("数据接收完毕");
            //6. 服务端发送数据给客户端
            os = socket.getOutputStream();
            os.write("你的图片很漂亮,我接收到了".getBytes());


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //7. 关闭相关的Socket和流
            try {
                if (os != null)
                    os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (is != null)
                    is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (socket != null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (serverSocket != null)
                    serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
相关推荐
大树886 小时前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠6 小时前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush46 小时前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5207 小时前
Linux 11 动态监控指令top
linux
小宇宙Zz7 小时前
Maven依赖冲突
java·服务器·maven
网络研究院8 小时前
2026年网络安全
网络·安全·法律·法规·趋势·发展
酣大智8 小时前
ARP代理--工作原理
运维·网络·arp·arp代理
treesforest8 小时前
AI安全系统如何识别异常访问?IP风险识别正在成为关键能力
网络·人工智能·tcp/ip·安全·web安全
不会C语言的男孩8 小时前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言
shushangyun_8 小时前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化