java取非io的网卡_Java - 网络IO

发展历程

Java1.0开始提供的IO都同步阻塞IO,即BIO。

Java1.4开始提供了同步非阻塞IO,即NIO。

Java1.7开始出现的NIO2.0版本,真正提供了异步非阻塞IO,即AIO。

引申:什么是“同步/异步”?什么是“阻塞/非阻塞”?

一个IO操作其实分成了两个步骤:发起IO请求和实际的IO操作。

同步IO和异步IO的区别就在于第二个步骤是否阻塞,如果实际的IO读写阻塞请求进程,那么就是同步IO。

阻塞IO和非阻塞IO的区别在于第一步,发起IO请求是否会被阻塞,如果阻塞直到完成那么就是传统的阻塞IO,如果不阻塞,那么就是非阻塞IO。

很明显,通常来说,非阻塞IO比阻塞IO效率高,异步IO比同步IO效率高

BIO

Blocking IO - (同步)阻塞IO

根据Linux IO模型可知,BIO的IO都是阻塞的。

在此种方式下,用户进程在发起一个IO操作以后,必须等待IO操作的完成,只有当真正完成了IO操作以后,用户进程才能运行。JAVA传统的IO模型属于此种方式。

BIO的读写操作都是阻塞的,即调用到read()方法时,如果没有数据,会一直阻塞等待。BIO对应的形象比喻:打电话时,如果对方不说话,本方会一直等待。很显然,这个效率是很低的。

BIO网络编程示例

网络编程大部分都是基于C/S模式的。

TCP

TCP Server端使用ServerSocket类,负责绑定IP,启动监听端口。

TCP Client端使用Socket类,负责连接Server

UDP

Java通过DatagramPacket类和DatagramSocket类来使用UDP套接字,客户端和服务器端都通过DatagramSocket的send()方法和receive()方法来发送和接收数据,用DatagramPacket来包装需要发送或者接收到的数据。

发送信息时,Java创建一个包含待发送信息的DatagramPacket实例,并将其作为参数传递给DatagramSocket实例的send()方法;接收信息时,Java程序首先创建一个DatagramPacket实例,该实例预先分配了一些空间,并将接收到的信息存放在该空间中,然后把该实例作为参数传递给DatagramSocket实例的receive()方法

注意:如果该实例用来包装待接收的数据,则不指定数据来源的远程主机和端口,只需指定一个缓存数据的byte数组即可(在调用receive()方法接收到数据后,源地址和端口等信息会自动包含在DatagramPacket实例中),而如果该实例用来包装待发送的数据,则要指定要发送到的目的主机和端口。

public class ServerSocket implements java.io.Closeable {

public Socket accept() throws IOException;

public void bind(SocketAddress endpoint) throws IOException;

public void close() throws IOException;

}

Client端依赖Socket类,负责连接Server

public class Socket implements java.io.Closeable{

public void bind(SocketAddress bindpoint) throws IOException;

public void connect(SocketAddress endpoint) throws IOException;

public synchronized void close() throws IOException;

}

public class DatagramSocket implements java.io.Closeable {

public synchronized void bind(SocketAddress addr) throws SocketException;

public void connect(InetAddress address, int port);

public void send(DatagramPacket p) throws IOException;

public synchronized void receive(DatagramPacket p) throws IOException;

}

TCP

Server端

单线程模型

//服务端的端口号

int port = 8080;

//创建服务端Socket

ServerSocket server = new ServerSocket(port);

//与客户端建立连接的Socket

Socket socket = null;

while(true){

//等待客户端接入

socket = server.accept();

//创建InputStream,读入数据

BufferedReader in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));

//创建OutputStream,写出数据

PrintWriter out = new PrintWriter(this.socket.getOutputStream());

//从网络中读取数据

String body = in.readLine();

//将数据写入到网络

out.println(body);

}

多线程模型

//服务端的端口号

int port = 8080;

//创建服务端Socket

ServerSocket server = new ServerSocket(port);

//与客户端建立连接的Socket

Socket socket = null;

while(true){

//等待客户端接入

socket = server.accept();

//某个客服端接入后,启动新的线程,在新线程中与客户端进行读写交互

new Thread(new ServerHandler(socket)).start();

}

public class ServerHandler implements Runnable{

private Socket socket;

public ServerHandler(Socket socket){

this.socket = socket;

}

@Override

public void run(){

BufferedReader in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));

PrintWriter out = new PrintWriter(this.socket.getOutputStream());

while(true){

//从网络读取数据

String body = in.readLine();

//将数据写入到网络

out.println(body)

}

}

}

Client端

String ip = "127.0.0.1";

int port = 8080;

//连接远程Server

Socket socket = new Socket(ip, port);

//输入流

PrintWriter out = new PrintWriter(socket.getOutputStream());

//输出流

BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

//向Server发送信息

out.println("Hello World");

//从Server收到信息

String res = in.readLine();

UDP

UDP的通信建立的步骤

一个典型的UDP客户端要经过下面三步操作:

创建一个DatagramSocket实例,可以有选择地对本地地址和端口号进行设置,如果设置了端口号,则客户端会在该端口号上监听从服务器端发送来的数据;

使用DatagramSocket实例的send()和receive()方法来发送和接收DatagramPacket实例,进行通信;

通信完成后,调用DatagramSocket实例的close()方法来关闭该套接字。

由于UDP是无连接的,因此UDP服务端不需要等待客户端的请求以建立连接。另外,UDP服务器为所有通信使用同一套接字,这点与TCP服务器不同,TCP服务器则为每个成功返回的accept()方法创建一个新的套接字。

一个典型的UDP服务端要经过下面三步操作:

创建一个DatagramSocket实例,指定本地端口号,并可以有选择地指定本地地址,此时,服务器已经准备好从任何客户端接收数据报文;

使用DatagramSocket实例的receive()方法接收一个DatagramPacket实例,当receive()方法返回时,数据报文就包含了客户端的地址,这样就知道了回复信息应该发送到什么地方;

使用DatagramSocket实例的send()方法向服务器端返回DatagramPacket实例。

fe15720a74fa

image.png

Server端

//端口

int port = 8080;

//创建DatagramSocket

DatagramSocket server = new DatagramSocket(port);

byte[] recvBuf = new byte[100];

DatagramPacket recvPacket = new DatagramPacket(recvBuf , recvBuf.length);

//接收数据

server.receive(recvPacket);

String sendStr = "Hello ! I'm Server";

byte[] sendBuf;

sendBuf = sendStr.getBytes();

DatagramPacket sendPacket = new DatagramPacket(sendBuf , sendBuf.length , addr , port );

//发送数据

server.send(sendPacket);

Client端

//创建客户端

DatagramSocket client = new DatagramSocket();

String sendStr = "Hello! I'm Client";

byte[] sendBuf;

sendBuf = sendStr.getBytes();

InetAddress addr = InetAddress.getByName("127.0.0.1");

int port = 8080;

//构建发送数据包

DatagramPacket sendPacket = new DatagramPacket(sendBuf ,sendBuf.length , addr , port);

//发送数据

client.send(sendPacket);

byte[] recvBuf = new byte[100];

//构建结束数据包

DatagramPacket recvPacket = new DatagramPacket(recvBuf , recvBuf.length);

//接收数据

client.receive(recvPacket);

String recvStr = new String(recvPacket.getData() , 0 ,recvPacket.getLength());

System.out.println("收到:" + recvStr);

client.close();

NIO

Non-Blocking IO - 同步非阻塞IO

在此种方式下,用户进程发起一个IO操作以后便可返回做其它事情,但是用户进程需要时不时的询问IO操作是否就绪,这就要求用户进程不停的去询问,从而引入不必要的CPU资源浪费。其中目前JAVA的NIO就属于同步非阻塞IO。

NIO对应的形象比喻:打电话时,如果对方没有话说,先挂掉电话,干点其他事情。过段时间再打过去,看看对方有没有话要说。如果对方有话要说,则拿着电话听对方说话。如此循环往复。

Java NIO编程是一个很重要的部分,会做专门的介绍:

Java NIO...

AIO

异步非阻塞IO

适用场景

BIO、NIO、AIO适用场景分析:

BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。

NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。

AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。

参考

要获取CentOS 7网卡信息,可以通过Java的系统命令执行功能来实现。以下是获取网卡信息的步骤: 1. 使用Java的ProcessBuilder类创建一个新进程,并执行"ifconfig"命令。 2. 将该进程的输出流连接到Java程序中,以便读取命令的输出。 3. 通过读取进程的输出流,获取ifconfig命令的执行结果。 4. 对命令输出进行解析,提取所需的网卡信息。 5. 将提取的网卡信息进行处理,比如保存到一个数据结构中或将其打印出来。 下面是一个简单的示例代码: ```java import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class GetCentosNetworkInfo { public static void main(String[] args) { try { // 执行ifconfig命令 ProcessBuilder processBuilder = new ProcessBuilder("ifconfig"); Process process = processBuilder.start(); // 读取命令的输出 BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; StringBuilder output = new StringBuilder(); while ((line = reader.readLine()) != null) { output.append(line).append("\n"); } // 解析输出,提取网卡信息 String networkInfo = output.toString(); String[] networkInfoArray = networkInfo.split("\n\n"); // 处理网卡信息 for (String network : networkInfoArray) { if (network.contains("inet")) { System.out.println(network); } } // 关闭资源 reader.close(); process.destroy(); } catch (IOException e) { e.printStackTrace(); } } } ``` 这段代码执行ifconfig命令,并将结果输出到控制台。如果想要保存网卡信息,可以将其存储到一个字符串、数组或集合中进行进一步处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值