java网络编程

时间:2024-11-17 15:42:25

网络编程概述

java实现了一个跨平台的网络库,程序员面对的是一个统一的网络编程环境。即里面有类包,直接调用就可以了。

软件架构:

  • C/S架构,客户端和服务端
  • B/S架构,浏览器和服务器

无论哪种架构,都离不开网络的支持,网络编程,即在一定的协议下,实现两台计算机的通信的程序。
实际上一些C/S也融合了B/S,所以有未更新的客户端也能看到新的功能页面。

网络基础

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

实现网络通信,解决的问题:

  • 如何准确定位网络上的一台主机或多台主机?-》IP地址
  • 如何定位主机上特定的应用?-》端口号
  • 如何可靠、高效的进行传输?-》规范网络通信协议

通信要素:IP地址和域名

IP:互联网协议地址,给网络中的设备作唯一的编号。

IP地址分类方式:IPV4,IPV6

  • 了解IPV4和IPV6

  • 公网地址和私有地址

    • 192.168.开头的就是私有地址

本地回路地址:127.0.0.1就代表了本地本机IP地址了,不用ipconfig去查了。

域名解析:连接网络时输入主机域名,域名服务器Domain Name System将域名转化为IP地址,才能和主机建立连续

端口号:唯一标识设备中的进程

网络通信协议:常使用TCP/IP四层协议

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

掌握两个实例,如下示例:

public class InetAddressTest {
    public static void main(String[] args) {
        // 实例化
        try {
            InetAddress inet1 = InetAddress.getByName("192.168.1.1");
            System.out.println(inet1);

            InetAddress inet2 = InetAddress.getByName("www.baidu.com");
            System.out.println(inet2);

            // 获取本机地址
            InetAddress inet3 = InetAddress.getLocalHost();
            System.out.println(inet3);
            
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

    }
}

掌握两个方法:

// 获取域名
            String hostName = inet2.getHostName();
            String address = inet2.getHostAddress();// 获取ip地址
            System.out.println(hostName);
            System.out.println(address);

TCP与UDP协议剖析,TCP编程

java.net提供了低层次的通信细节,提供了常见的网络协议的支持:

  • UDP,用户数据表协议,

  • TCP,传输控制协议,

TCP三次握手:发送数据的准备阶段,客户端与服务端的三次交互,以保证连接的可靠性

  • 第一次,客户端向服务端发起连接请求

  • 第二次握手,服务端发送针对客户端TCP请求的确认

  • 第三次,客户端发送确认的确认

TCP,释放时经过4次挥手

Socket类:网络上具有唯一标识的IP地址和端口号组合在一起构成唯一能识别的标识符套接字socket。

网络通信实际就是socket间的通信。

TCP示例-客户端发送内容给服务端

package com.atguigu02.tcpudp;

import org.testng.annotations.Test;

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.nio.charset.StandardCharsets;

/**
 * @DESC: 客户端发送内容给服务端,服务端将内容输出
 * 先启动服务端,再启动客户端
 */
public class TCPTest1 {
    // 客户端
    @Test
    public void client() {
        Socket socket = null;
        OutputStream os = null;
        try {
            // 创建一个socket
//            InetAddress inetAddress = InetAddress.getByName("192.168.1.1");
            InetAddress inetAddress = InetAddress.getLocalHost();
            int port = 8989;
            socket = new Socket(inetAddress, port);

            // 发送数据
            os = socket.getOutputStream();
            os.write("你好客户端发来的数据".getBytes(StandardCharsets.UTF_8));


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭socket

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

                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    // 服务端
    @Test
    public void server() {
        ServerSocket serverSocket = null;
        Socket socket = null; // 阻塞式的方法
        InputStream is = null;
        try {
            // 创建ServerSocket
            int port = 8989; // 与客户端中请求的服务端的端口号一样
            serverSocket = new ServerSocket(port);


            // 调用accept方法,接受客户端的socket
            socket = serverSocket.accept();
            System.out.println("服务端已开启");

            // 接收数据
            is = socket.getInputStream();
            // 回顾io流接收数据
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1) {
                // 字符串
                String s = new String(buffer, 0, len);
                System.out.println(s);

            }
            System.out.println("\n数据接收完毕");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭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();
            }
        }


    }
}


如图所示:
在这里插入图片描述
注意服务端接收那里,字节流一般不处理文本文件,引入字节数组输出流,下面是修改的,

 // 下面是修正后的接收内容
            byte[] buffer = new byte[5];
            int len;
            ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 内部维护了一个byte数组
            while ((len = is.read(buffer)) != -1){
                baos.write(buffer, 0,  len);
            }
            System.out.println(baos.toString());
            System.out.println("\n数据接收完毕");

客户端发送文件给服务端

还是同样的流程,注意读写过程需要掌握。

package com.atguigu02.tcpudp;

import org.testng.annotations.Test;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @DESC: 客户端发送文件给服务端
 */
public class TCPTest2 {
    @Test
    public void client() {
        Socket socket = null;
        FileInputStream fis = null;
        OutputStream os = null;
        try {
            // 创建socket
            // socket需要服务端的ip地址或者域名,以及端口号
            // 获取ip,定义端口号
            InetAddress localHost = InetAddress.getLocalHost();
//        InetAddress localHost = InetAddress.getByName('127.0.0.1');
            int port = 9090;
            socket = new Socket(localHost, port);

            // 创建File的实例,FileInputStream的实例
            File file = new File("E://mycodes//ideaProject//shangguigujavastudy//JavaSECode//chapter16_net//src//test.png");
            // 创建输入流
            fis = new FileInputStream(file);

            // 通过Socket获取输出流
            os = socket.getOutputStream();
            // 读写数据
            byte[] buffer = new byte[1024];
            int len;
            while((len = fis.read(buffer)) != -1) {
                // 写数据
                os.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            System.out.println("客户端数据发送完毕");
            // 关闭socket和其他流
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    @Test
    public void server() {
        ServerSocket serverSocket = null;
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            // 创建serverSocket
            int port = 9090;
            serverSocket = new ServerSocket(port);
            // 接收来自客户端的socket
            Socket accept = serverSocket.accept();
            // 获取一个输入流
            is = accept.getInputStream();
            // 同样也是文件,需要保存到服务端当中,使用到输出流保存
            File file = new File("E://mycodes//ideaProject//shangguigujavastudy//JavaSECode//chapter16_net//src//test_server.png");
            fos = new FileOutputStream(file);
            // 读写过程,把接受到的写进去
            byte[] buffer = new byte[1024];
            int len;
            while((len = is.read(buffer)) != -1){
                fos.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            System.out.println("服务端接收文件成功");
            // 关闭相关的socket和流
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


客户端发送文件给服务端并返回信息给客户端

客户端标记不再发送数据了,接收服务端返回的数据。

package com.atguigu02.tcpudp;

import org.testng.annotations.Test;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @DESC: 客户端发送文件给服务端
 */
public class TCPTest3 {
    @Test
    public void client() {
        Socket socket = null;
        FileInputStream fis = null;
        OutputStream os = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
            // 创建socket
            // socket需要服务端的ip地址或者域名,以及端口号
            // 获取ip,定义端口号
            InetAddress localHost = InetAddress.getLocalHost();
//        InetAddress localHost = InetAddress.getByName('127.0.0.1');
            int port = 9090;
            socket = new Socket(localHost, port);

            // 创建File的实例,FileInputStream的实例
            File file = new File("E://mycodes//ideaProject//shangguigujavastudy//JavaSECode//chapter16_net//src//test.png");
            // 创建输入流
            fis = new FileInputStream(file);

            // 通过Socket获取输出流
            os = socket.getOutputStream();
            // 读写数据
            byte[] buffer = new byte[1024];
            int len;
            while((len = fis.read(buffer)) != -1) {
                // 写数据
                os.write(buffer, 0, len);
            }
            System.out.println("客户端数据发送完毕");

            // 接收来自服务端的信息,应该是输入流
            // 接收服务端的信息,应该先表示自己不再发送数据了
            socket.shutdownOutput();
            is = socket.getInputStream();
            // 使用ByteArrayOutputStream防止乱码,内部维护了一个byte字节数组
            baos = new ByteArrayOutputStream(); // 写到内存里
            byte[] buffer1 = new byte[5];
            int len1;
            while((len1 = is.read(buffer1)) != -1){
                baos.write(buffer1,0, len1);
            }
            System.out.println(baos.toString());



        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                baos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 关闭socket和其他流
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

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