Java网络编程基础

本文涉及的产品
对象存储 OSS,20GB 3个月
.cn 域名,1个 12个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: Java网络编程基础

本文的图片大部分引用于韩顺平老师,对网络编程基础做了总结,至于更详细的内容,大家可以去看计算机网络

一、网络的相关概念

1.网络通信

在这里插入图片描述

2.网络

在这里插入图片描述
网络编程的目的:直接或间接地通过网络协议与其他计算机实现数据交换进行通讯
要想实现网络编程,需要关注两个问题:
1.如何准确定位网络上的一台或多台主机,定位主机上的特定应用
2.找到主机以后怎么进行可靠高效的数据传输

3 .IP地址

在这里插入图片描述
IP地址就是网络上定位的一台主机,端口号就是定位这台主机是哪一个应用在进行通信,端口号用来区分一台主机上面的不同应用程序
在这里插入图片描述

4.ipv4地址分类

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

5.域名和端口号

比如说我们想要访问一个网站,由于IP地址难以记忆,我们一般在浏览器上写的是域名,域名经过DNS域名解析服务器,会把域名解析出来,看它的IP是多少,解析完以后,再拿这个IP地址去访问对应的服务器,就可以把这个资源访问到了
在这里插入图片描述
不同的进程对应不同的端口号
端口号与IP地址的组合得出一个网络套接字:Socket
在这里插入图片描述
一个服务要接收和发送数据的话,需要有一个端口。端口就类似于人的耳朵,我们要听懂别人的话,必须要有耳朵

在这里插入图片描述

6.网络通信协议

!

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

OSI模型过于理想化,没有被广泛推广
在这里插入图片描述

7. TCP和UDP

在这里插入图片描述
TCP类似于打电话
UDP类似于发短信
TCP三次握手
举一个生活中的小例子:打电话
打电话的时候,假设一个叫tom,一个叫kim,tom想要打电话和kim说事情,这个时候,电话必须打通,才可以传递信息,就类似于TCP连接。为了确保kim有在听,tom在传递信息之前先问一句,你在听吗?kim听到后就回说在听,然后tom就说我要开始说事情了,紧接着开始说事情
在这里插入图片描述
UDP协议无法保证传输的数据一定被接收到
UDP协议就是没有确认对方是否能够接收到消息,就直接传输信息
比如说:你发送信息给别人,但是这个电话号码可能停机了或者说注销了,你不能确保别人能接收消息,类似于UDP协议
在这里插入图片描述
假如说现在有一个人也想要打电话给kim,由于kim这个时候在和tom打电话,他们两个如果电话没有挂掉,这个人的电话是打不通的,就类似于TCP协议要释放已经建立的连接

tom发信息给kim,另外一个人同样也可以发信息给kim,就类似于UDP协议不需要释放资源

在这里插入图片描述

二、InetAddress 类

一个InetAddress类的对象就当于是一个IP地址

//File file=new File("hello.txt");
    //比如说在这里file就对应内存中的hello.txt这个文件
    //类似于这个
     //inet1就对应一个具体的IP地址
    InetAddress inet1=InetAddress.getByName("192.168.10.14");
   //写上主机名就可以返回对应的对象

   

1.相关方法

getByName(String host) 、 getLocalHost()
两个常用方法:getHostName() 获取域名 / getHostAddress() 获取主机地址
在这里插入图片描述

2.实例操作

在这里插入图片描述

package com.zyh.java;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**InetAddress类的使用
 * @author zengyihong
 * @create 2022--02--27 8:46
 */
public class InetAddressMethod {
    public static void main(String[] args) throws UnknownHostException {
  //获取本机的InetAddress对象
        InetAddress localHost = InetAddress.getLocalHost();
        
        //计算机名称和识别到的ip地址
        System.out.println(localHost);

        //我们也可以根据主机名来获取InetAddress对象
        InetAddress byName = InetAddress.getByName("这里写上你的主机名");
        System.out.println("host="+byName);

        //根据域名来返回InetAddress对象
        InetAddress byName1 = InetAddress.getByName("www.baidu.com");
        System.out.println("百度:"+byName1);

        //根据InetAddress对象获取对呀的主机地址
        String hostAddress = byName1.getHostAddress();
        System.out.println(hostAddress);//ip地址

        //通过InetAddress对象,获取对应的主机名或者域名
        String hostName = byName1.getHostName();
        System.out.println(hostName);

    }
}

三、Socket

Socket就类似于通信的通道,发送数据是通过socket
在这里插入图片描述
在这里插入图片描述

两台主机要通信首先要建立连接,就相当于是建立一个数据通道

客户端发起连接,服务器端接收连接就会形成这样一个数据通道

Socket有两个编程方式:TCP编程和UDP编程

1.TCP网络通信编程

1.1基本介绍

在这里插入图片描述
Socket最后记得关闭,不然连接越来越多,最后就导致无法连接

1.2案例1:客户端发送信息给服务端

在这里插入图片描述
思路:
在这里插入图片描述
ServerSocket可以有多个Socket,也就是说服务器端可以和多个客户端连接,否则就不能处理多并发问题
在这里插入图片描述
服务器端:

package com.zyh.java;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**服务器端
 * @author zengyihong
 * @create 2022--02--27 9:25
 */
public class SocketTCP01Server {
    public static void main(String[] args) throws IOException {
        //在本机的9999端口监听,等待连接
        //要求:本机没有其他服务监听这个端口
        //ServerSocket可以有多个Socket 通过accept可以返回多个Socket
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务器端在9999端口等待连接...");
        //如果没有客户端连接此端口,程序就会阻塞,等待连接
        //如果有客户端连接,则返回Socket对象
        Socket socket = serverSocket.accept();
        //没有连接的话,下面的代码都不会运行

        System.out.println("服务器端 socket="+socket.getClass());

        System.out.println("服务器端开始接收信息");
        //连接以后要读取客户端发送的信息
        //通过IO读取
        InputStream inputStream = socket.getInputStream();
        byte[] bytes=new byte[10];
        int len;
        while ((len=inputStream.read(bytes))!=-1){
            String s = new String(bytes, 0, len);
            System.out.print (s);
        }
        //关闭流和socket
        inputStream.close();
        socket.close();
        serverSocket.close();
    }
}

客户端:

package com.zyh.java;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/**
 * 客户端
 *
 * @author zengyihong
 * @create 2022--02--27 9:31
 */
public class SocketTCP01Client {
    public static void main(String[] args) throws IOException {
    //连接服务器端 (ip,端口)
        //连接某一台主机的9999端口,如果连接成功,返回socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        System.out.println("客户端 socket返回="+socket.getClass());

        //连接上后,生成Socket,发送数据给服务端,通过socket,getOutputStream()
        //得到和socket对象关联的输出流对象
        System.out.println("客户端要开始发消息给服务端了");
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello,server".getBytes());

        //关闭流对象和socket
        outputStream.close();
        socket.close();
        System.out.println("客户端退出");
    }
}

运行效果:

在服务器端:

服务器端在9999端口等待连接...
服务器端 socket=class java.net.Socket
hello,server

在客户端:

客户端 socket返回=class java.net.Socket
客户端退出

1.3案例2:客户端发信息给服务器端,并接收服务器端发回来的消息

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

注意:服务器端发消息给客户端的时候,客户端并不知道服务器端什么时候发送信息结束,也就是发送信息的时候,要有一个结束标记,不然就会一直等待,同样的,另外一个发送信息的时候,发送结束也应该要有一个结束标记,不然就不知道对方还要不要继续发送信息

服务器端:

package com.zyh.java;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**服务器端
 * @author zengyihong
 * @create 2022--02--27 9:25
 */
public class SocketTCP02Server {
    public static void main(String[] args) throws IOException {
        //在本机的9999端口监听,等待连接
        //要求:本机没有其他服务监听这个端口
        //ServerSocket可以有多个Socket 通过accept可以返回多个Socket
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务器端在9999端口等待连接...");
        //如果没有客户端连接此端口,程序就会阻塞,等待连接
        //如果有客户端连接,则返回Socket对象
        Socket socket = serverSocket.accept();
        //没有连接的话,下面的代码都不会运行

        System.out.println("服务器端 socket="+socket.getClass());

        System.out.println("服务器端开始接收信息");
        //连接以后要读取客户端发送的信息
        //通过IO读取
        InputStream inputStream = socket.getInputStream();
        byte[] bytes=new byte[10];
        int len;
        while ((len=inputStream.read(bytes))!=-1){
            String s = new String(bytes, 0, len);
            System.out.print (s);
        }
        //获取 socket 相关联的输出流
    OutputStream outputStream = socket.getOutputStream();
    outputStream.write("hello, client".getBytes());
//      设置结束标记
    socket.shutdownOutput();
        //关闭流和socket
        outputStream.close();
        inputStream.close();
        socket.close();
        serverSocket.close();
    }
}

客户端:

package com.zyh.java;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/**
 * 客户端
 *
 * @author zengyihong
 * @create 2022--02--27 9:31
 */
public class SocketTCP02Client {
    public static void main(String[] args) throws IOException {
    //连接服务器端 (ip,端口)
        //连接某一台主机的9999端口,如果连接成功,返回socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        System.out.println("客户端 socket返回="+socket.getClass());

        //连接上后,生成Socket,发送数据给服务端,通过socket,getOutputStream()
        //得到和socket对象关联的输出流对象
        System.out.println("客户端要开始发消息给服务端了");
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello,server".getBytes());
        //      设置结束标记
socket.shutdownOutput();

//  获取和 socket 关联的输入流.  读取数据(字节) ,并显示
    InputStream inputStream = socket.getInputStream();
    byte[] buf = new byte[1024];
    int readLen = 0;
    while ((readLen = inputStream.read(buf)) != - 1) {
            System.out.println(new String(buf, 0, readLen));
    }

        //关闭流对象和socket
        inputStream.close();
        outputStream.close();
        socket.close();
        System.out.println("客户端退出");
    }
}
运行效果:

在服务器端:

服务器端在9999端口等待连接...
服务器端 socket=class java.net.Socket
hello,server

在客户端:

客户端 socket返回=class java.net.Socket
hello,client
客户端退出

### 1.4案例3:使用字符流
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/ffa94cb1efac4afeabdafef4af2bc35c.png)
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/1060a10759d44b6cae73b71370233e8f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASmF2YeeahOWtpuS5oOS5i-i3rw==,size_19,color_FFFFFF,t_70,g_se,x_16)

客户端

package com.hspedu.socket;

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

@SuppressWarnings({"all"})
public class SocketTCP03Server {
public static void main(String[] args) throws IOException {
//思路
//1. 在本机 的 9999 端口监听, 等待连接
// 细节: 要求在本机没有其它服务在监听 9999

// 细节: 这个 ServerSocket 可以通过 accept() 返回多个 Socket[多个客户端连接服务器的并发] ServerSocket serverSocket = new ServerSocket(9999);

System.out.println("服务端,在 9999 端口监听,等待连接..");

//2. 当没有客户端连接 9999 端口时,程序会 阻塞, 等待连接
// 如果有客户端连接,则会返回 Socket 对象,程序继续

Socket socket = serverSocket.accept();

System.out.println("服务端 socket =" + socket.getClass());

//
//3. 通过 socket.getInputStream() 读取客户端写入到数据通道的数据, 显示

InputStream inputStream = socket.getInputStream();

//4. IO 读取, 使用字符流, 使用 InputStreamReader 将 inputStream 转成字符流

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 
String s = bufferedReader.readLine();
System.out.println(s);//输出

//5. 获取 socket 相关联的输出流

OutputStream outputStream = socket.getOutputStream();

// 使用字符输出流的方式回复信息

BufferedWriter bufferedWriter = new BufferedWriter(new     OutputStreamWriter(outputStream)); 
bufferedWriter.write("hello client  字符流");
bufferedWriter.newLine();//  插入一个换行符,表示回复内容的结束
bufferedWriter.flush();//注意需要手动的 flush

//6.关闭流和 socket
bufferedWriter.close();
bufferedReader.close();
socket.close();
serverSocket.close();//关闭    

}
}

服务端:

package com.hspedu.socket;
import java.io.*;
import java.net.InetAddress; import java.net.Socket;

/**

  • 客户端,发送 "hello, server" 给服务端, 使用字符流 */

@SuppressWarnings({"all"})
public class SocketTCP03Client {
public static void main(String[] args) throws IOException {
//思路
//1. 连接服务端 (ip , 端口)
//解读: 连接本机的 9999 端口, 如果连接成功,返回 Socket 对象

Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
System.out.println("客户端 socket 返回=" + socket.getClass());

//2. 连接上后,生成 Socket, 通过 socket.getOutputStream()
// 得到 和 socket 对象关联的输出流对象

OutputStream outputStream = socket.getOutputStream();

//3. 通过输出流,写入数据到 数据通道, 使用字符流

BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); 
bufferedWriter.write("hello, server  字符流");
bufferedWriter.newLine();
//插入一个换行符,表示写入的内容结束,  注意,要求对方使用 readLine()
//!!!! bufferedWriter.flush();
//  如果使用的字符流,需要手动刷新,否则数据不会写入数据通道


//4. 获取和 socket 关联的输入流. 读取数据(字符) ,并显示

InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new     InputStreamReader(inputStream)); String s = bufferedReader.readLine();
System.out.println(s);

//5. 关闭流对象和 socket, 必须关闭

bufferedReader.close();//关闭外层流
bufferedWriter.close();
socket.close();
System.out.println("客户端退出.....");

}
}

运行结果:
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/c75376333a1a450cb418e9f62257d95b.png)
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/c5103e3f6aa6483e92e5f14831abdb8e.png)
### 1.5案例4:发送图片
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/f00aa4a42ca1432da5fdc1d35ccfd326.png)
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/00d70be020634289ae78504f492a0802.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASmF2YeeahOWtpuS5oOS5i-i3rw==,size_19,color_FFFFFF,t_70,g_se,x_16)
### 1.6netstat指令
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/a1794bf2f61c4cb0a44498c72e16a6db.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASmF2YeeahOWtpuS5oOS5i-i3rw==,size_19,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/e4bd6868a3f4426c93b200f322ce77aa.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASmF2YeeahOWtpuS5oOS5i-i3rw==,size_20,color_FFFFFF,t_70,g_se,x_16)

netstat - anb表示我们在查看程序的时候,知道是哪一个程序在占用这个端口

###  1.7 TCP 网络通讯不为人知的秘密
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/2414e45ad28b4c44bbe7ccf216bdca35.png)
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/538214dd548c40d99801bb3225cdbf77.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASmF2YeeahOWtpuS5oOS5i-i3rw==,size_20,color_FFFFFF,t_70,g_se,x_16)

当客户端和服务器连接成功以后,客户端这里也有一个端口,它的端口是不确定的,是由TCP/IP分配的。客户端这里对应的端口和服务器端通讯

当传输结束以后,客户端的端口就被释放了
## 2.UDP网络编程(了解)
用得相对比较少,但是效率比较高
### 1. 基本介绍
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/9785bbd8a194497e9de3f0932437892a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASmF2YeeahOWtpuS5oOS5i-i3rw==,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/3d66337753b5465a824d2a623e852f3f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASmF2YeeahOWtpuS5oOS5i-i3rw==,size_19,color_FFFFFF,t_70,g_se,x_16)
### 2.基本流程
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/d2096115e6584b52819865c877bbe50a.png)
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/e390d8206a32414888dba9e865f2e155.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASmF2YeeahOWtpuS5oOS5i-i3rw==,size_9,color_FFFFFF,t_70,g_se,x_16)
### 3.案例
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/7ad21366911d4d29832f6065af59c060.png)
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/19da9f04564740078c8198250fb730b4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASmF2YeeahOWtpuS5oOS5i-i3rw==,size_19,color_FFFFFF,t_70,g_se,x_16)
 

package com.zyh.java.udptest;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**UDP接收端

  • @author zengyihong
  • @create 2022--02--27 12:38

*/
public class SocketUDP01Reciver {

public static void main(String[] args) throws IOException {
    //创建一个DatagramSocket对象,准备在9999端口接收数据
    DatagramSocket datagramSocket=new DatagramSocket(9999);
    //创建 DatagramPacket对象,准备接收数据
    //UDP数据包每一个大小被限制在64K内,不适合传输大量数据
    byte[] bytes=new byte[1024];
    DatagramPacket datagramPacket=new DatagramPacket(bytes,bytes.length);

    //调用接收方法,把通过网络传输的DatagramPacket对象
    //填充到packet对象
    //会在9999端口等待,如果有数据包发送到此端口,就会接收到数据
    //如果没有数据包发送到9999端口,就会阻塞,一直等,直到有数据传输
    System.out.println("接收端A等待接收数据...");
    datagramSocket.receive(datagramPacket);

    //把datagramPacket进行拆包,取出数据,并显示
    //因为数据的传输被包装起来了
    //返回实际接收的长度
    int length = datagramPacket.getLength();
    //接收到的数据
    byte[] data = datagramPacket.getData();
    String s = new String(data, 0, length);
    System.out.println(s);
    //关闭资源
    datagramSocket.close();
    System.out.println("A端退出");
}

}

package com.zyh.java.udptest;

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

/**UDP发送端

  • 发送端B也可以接收数据
  • 发送端将来也可以是接收端
  • @author zengyihong
  • @create 2022--02--27 12:39

*/
public class SocketUDP01Send {

public static void main(String[] args) throws IOException {
    //创建DatagramSocket对象,准备发送和接收数据
    //准备在9998端口接收数据
    DatagramSocket socket=new DatagramSocket(9998);

    //把要发送的数据封装到DatagramPacket对象 内容字节数组,长度,主机(IP),端口
    byte[] buff= "hello,明天吃火锅".getBytes();
    //ipconfig可以查看网络配置
    DatagramPacket packet=new DatagramPacket(buff,buff.length,InetAddress.getLocalHost(),9999);

    //发送数据
    socket.send(packet);
    //关闭资源
    socket.close();
    System.out.println("B端退出");



}

}

运行结果

接收端A等待接收数据...
hello,明天吃火锅
A端退出

B端退出`

相关文章
|
5天前
|
Java
java网络编程 UDP通信协议实现局域网内文件的发送和接收
java网络编程 UDP通信协议实现局域网内文件的发送和接收
java网络编程 UDP通信协议实现局域网内文件的发送和接收
|
11天前
|
网络协议 Java 关系型数据库
16 Java网络编程(计算机网络+网络模型OSI/TCP/IP+通信协议等)
16 Java网络编程(计算机网络+网络模型OSI/TCP/IP+通信协议等)
41 2
|
20天前
|
缓存 网络协议 算法
(二)Java网络编程之爆肝HTTP、HTTPS、TLS协议及对称与非对称加密原理!
作为一名程序员,尤其是Java程序员,那必须得了解并掌握HTTP/HTTPS相关知识。因为在如今计算机网络通信中,HTTP协议的作用功不可没,无论是日常上网追剧、冲���、亦或是接口开发、调用等,必然存在HTTP的“影子”在内。尤其对于WEB开发者而言,HTTP几乎是每天会打交道的东西。
45 10
|
19天前
|
Java 应用服务中间件 Linux
(九)Java网络编程无冕之王-这回把大名鼎鼎的Netty框架一网打尽!
现如今的开发环境中,分布式/微服务架构大行其道,而分布式/微服务的根基在于网络编程,而Netty恰恰是Java网络编程领域的无冕之王。Netty这个框架相信大家定然听说过,其在Java网络编程中的地位,好比JavaEE中的Spring。
|
19天前
|
安全 Java Linux
(七)Java网络编程-IO模型篇之从BIO、NIO、AIO到内核select、epoll剖析!
IO(Input/Output)方面的基本知识,相信大家都不陌生,毕竟这也是在学习编程基础时就已经接触过的内容,但最初的IO教学大多数是停留在最基本的BIO,而并未对于NIO、AIO、多路复用等的高级内容进行详细讲述,但这些却是大部分高性能技术的底层核心,因此本文则准备围绕着IO知识进行展开。
|
19天前
|
存储 Java Unix
(八)Java网络编程之IO模型篇-内核Select、Poll、Epoll多路复用函数源码深度历险!
select/poll、epoll这些词汇相信诸位都不陌生,因为在Redis/Nginx/Netty等一些高性能技术栈的底层原理中,大家应该都见过它们的身影,接下来重点讲解这块内容。
|
20天前
|
网络协议 Java 数据处理
(一)Java网络编程之计网基础、TCP-IP协议簇、TCP、UDP协议及腾讯QQ通信原理综述
就目前而言,多数网络编程的系列的文章都在围绕着计算机网络体系进行阐述,但其中太多理论概念,对于大部分开发者而言,用途甚微。因此,在本系列中则会以实际开发者的工作为核心,从Java程序员的角度出发,详细解读Java的网络编程核心内容。
|
1月前
|
网络协议 安全 Java
Java中的网络编程:Socket编程详解
Java中的网络编程:Socket编程详解
|
30天前
|
网络协议 Java Linux
|
1月前
|
安全 Java 网络安全
Java网络编程:高级应用与安全性探讨
Java网络编程:高级应用与安全性探讨