java nio学习_java nio学习[zt]

对相关类的简单介绍

java.nio.*, 据说它提供了一些更加底层的一些功能,如:类似windows环境下的AsyncSocket类的异步操作的功能,能显著降低server端程序的线程管理开销。

因为大多数应用是建立在TCP之上,所以在此只说说SocketChannel,ServerSocketChannel,Selector和ByteBuffer这几个类.前三个最终都源自channel类。而channel 类,可以理解为在具体I/O或文件对象之上抽象的一个操作对象,我们通过操作channel的读写达到对其对应的文件或I/O对象(包括socket)读写的目的。读写的内容在内存中放在ByteBuffer类提供的缓冲区。总而言之,channel作为一个桥梁,连接了I/O对象和内存中的ByteBuffer,实现了I/O的更高效的存取。

一个基于TCP的服务器端程序,必然有个侦听端和若干个通信端,它们在nio中由对应的ServerSocketChannel 和SocketChannel类来实现。为了达到异步I/O操作的目的,需要Selector类,它能检测到I/O对象的状态。

SocketChannel类是抽象类,通过调用它的静态函数open(),可生成一个SocketChannel对象,该对象对应一个java.net.Socket,可通过SocketChannel.socket()获得,而其对应的Socket也可通过调用函数getChannel()得到已建立的相应SocketChannel。

SocketChannel与它的socket是一一对应的。SocketChannel的操作与Socket也很相似.

ServerSocketChannel也是通过调用它的静态函数open()生成的,只是它不能直接调用bind()函数来绑定一个地址,需要它对应的ServerSocket来完成绑定工作,一般可按如下步骤做:

4f1150b881333f12a311ae9ef34da474.png ServerSocketChannel ssc = new ServerSocketChannel.open();

4f1150b881333f12a311ae9ef34da474.png    ssc.socket().bind(InetSocketAddress(host,port));

4f1150b881333f12a311ae9ef34da474.png

罗嗦了半天,还是看看最简单的C/S实现吧,服务器提供了基本的回射(echo)功能,其中提供了较详细的注释。

源码分析

1.服务器端:

4f1150b881333f12a311ae9ef34da474.png4f1150b881333f12a311ae9ef34da474.png//AsyncServer.java

4f1150b881333f12a311ae9ef34da474.png//by zztudou@163.com4f1150b881333f12a311ae9ef34da474.png

4f1150b881333f12a311ae9ef34da474.pngimportjava.nio.channels.SocketChannel;

4f1150b881333f12a311ae9ef34da474.pngimportjava.nio.channels.ServerSocketChannel;

4f1150b881333f12a311ae9ef34da474.pngimportjava.nio.channels.SelectionKey;

4f1150b881333f12a311ae9ef34da474.pngimportjava.nio.channels.Selector;

4f1150b881333f12a311ae9ef34da474.pngimportjava.nio.ByteBuffer;

4f1150b881333f12a311ae9ef34da474.pngimportjava.nio.channels.SelectableChannel;

4f1150b881333f12a311ae9ef34da474.pngimportjava.nio.channels.spi.SelectorProvider;

4f1150b881333f12a311ae9ef34da474.pngimportjava.net.ServerSocket;

4f1150b881333f12a311ae9ef34da474.pngimportjava.net.Socket;

4f1150b881333f12a311ae9ef34da474.pngimportjava.net.InetSocketAddress;

4f1150b881333f12a311ae9ef34da474.pngimportjava.net.SocketAddress;

4f1150b881333f12a311ae9ef34da474.pngimportjava.util.Iterator;

4f1150b881333f12a311ae9ef34da474.pngimportjava.util.LinkedList;

4f1150b881333f12a311ae9ef34da474.pngimportjava.io.IOException;

4f1150b881333f12a311ae9ef34da474.png

1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifclassAsyncServerimplementsRunnable9b8a8a44dd1c74ae49c20a7cd451974e.png

d18c02628675d0a2c816449d98bda930.pngprivateByteBuffer r_buff=ByteBuffer.allocate(1024);

d18c02628675d0a2c816449d98bda930.pngprivateByteBuffer w_buff=ByteBuffer.allocate(1024);

d18c02628675d0a2c816449d98bda930.pngprivatestaticintport=8848;

d18c02628675d0a2c816449d98bda930.png 

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifpublicAsyncServer()9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.pngnewThread(this).start();

ecedf933ec37d714bd4c2545da43add2.png }d18c02628675d0a2c816449d98bda930.png 

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifpublicvoidrun()9b8a8a44dd1c74ae49c20a7cd451974e.png{    

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.giftry9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png//生成一个侦听端d18c02628675d0a2c816449d98bda930.pngServerSocketChannel ssc=ServerSocketChannel.open();

d18c02628675d0a2c816449d98bda930.png//将侦听端设为异步方式d18c02628675d0a2c816449d98bda930.pngssc.configureBlocking(false);

d18c02628675d0a2c816449d98bda930.png//生成一个信号监视器d18c02628675d0a2c816449d98bda930.pngSelector s=Selector.open();

d18c02628675d0a2c816449d98bda930.png//侦听端绑定到一个端口d18c02628675d0a2c816449d98bda930.pngssc.socket().bind(newInetSocketAddress(port));

d18c02628675d0a2c816449d98bda930.png//设置侦听端所选的异步信号OP_ACCEPTd18c02628675d0a2c816449d98bda930.pngssc.register(s,SelectionKey.OP_ACCEPT);

d18c02628675d0a2c816449d98bda930.png   

d18c02628675d0a2c816449d98bda930.png   System.out.println("echo server has been set up 

9b8a8a44dd1c74ae49c20a7cd451974e.png

9b8a8a44dd1c74ae49c20a7cd451974e.png");

d18c02628675d0a2c816449d98bda930.png 

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifwhile(true)9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.pngintn=s.select();

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(n==0)9b8a8a44dd1c74ae49c20a7cd451974e.png{//没有指定的I/O事件发生d18c02628675d0a2c816449d98bda930.pngcontinue;

ecedf933ec37d714bd4c2545da43add2.png    }d18c02628675d0a2c816449d98bda930.png    Iterator it=s.selectedKeys().iterator();     

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifwhile(it.hasNext())9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png     SelectionKey key=(SelectionKey) it.next();

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(key.isAcceptable())9b8a8a44dd1c74ae49c20a7cd451974e.png{//侦听端信号触发d18c02628675d0a2c816449d98bda930.pngServerSocketChannel server=(ServerSocketChannel) key.channel();

d18c02628675d0a2c816449d98bda930.png//接受一个新的连接d18c02628675d0a2c816449d98bda930.pngSocketChannel sc=server.accept();

d18c02628675d0a2c816449d98bda930.png      sc.configureBlocking(false);

d18c02628675d0a2c816449d98bda930.png//设置该socket的异步信号OP_READ:当socket可读时,

d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//触发函数DealwithData();d18c02628675d0a2c816449d98bda930.pngsc.register(s,SelectionKey.OP_READ);

ecedf933ec37d714bd4c2545da43add2.png     }97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(key.isReadable())9b8a8a44dd1c74ae49c20a7cd451974e.png{//某socket可读信号d18c02628675d0a2c816449d98bda930.pngDealwithData(key);

ecedf933ec37d714bd4c2545da43add2.png     }d18c02628675d0a2c816449d98bda930.png     it.remove();

ecedf933ec37d714bd4c2545da43add2.png    }ecedf933ec37d714bd4c2545da43add2.png   }ecedf933ec37d714bd4c2545da43add2.png  }97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifcatch(Exception e)9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png   e.printStackTrace(); 

ecedf933ec37d714bd4c2545da43add2.png  }ecedf933ec37d714bd4c2545da43add2.png }d18c02628675d0a2c816449d98bda930.png  

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifpublicvoidDealwithData(SelectionKey key)throwsIOException9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.pngintcount;

d18c02628675d0a2c816449d98bda930.png//由key获取指定socketchannel的引用d18c02628675d0a2c816449d98bda930.pngSocketChannel sc=(SocketChannel)key.channel();

d18c02628675d0a2c816449d98bda930.png  r_buff.clear();

d18c02628675d0a2c816449d98bda930.png//读取数据到r_buffd18c02628675d0a2c816449d98bda930.pngwhile((count=sc.read(r_buff))>0)

d18c02628675d0a2c816449d98bda930.png   ;

d18c02628675d0a2c816449d98bda930.png//确保r_buff可读d18c02628675d0a2c816449d98bda930.pngr_buff.flip();

d18c02628675d0a2c816449d98bda930.png  

d18c02628675d0a2c816449d98bda930.png  w_buff.clear();

d18c02628675d0a2c816449d98bda930.png//将r_buff内容拷入w_buffd18c02628675d0a2c816449d98bda930.pngw_buff.put(r_buff);

d18c02628675d0a2c816449d98bda930.png  w_buff.flip();

d18c02628675d0a2c816449d98bda930.png//将数据返回给客户端d18c02628675d0a2c816449d98bda930.pngEchoToClient(sc);

d18c02628675d0a2c816449d98bda930.png 

d18c02628675d0a2c816449d98bda930.png  w_buff.clear();

d18c02628675d0a2c816449d98bda930.png  r_buff.clear();

ecedf933ec37d714bd4c2545da43add2.png }d18c02628675d0a2c816449d98bda930.png 

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifpublicvoidEchoToClient(SocketChannel sc)throwsIOException9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.pngwhile(w_buff.hasRemaining())

d18c02628675d0a2c816449d98bda930.png   sc.write(w_buff);

ecedf933ec37d714bd4c2545da43add2.png }d18c02628675d0a2c816449d98bda930.png 

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifpublicstaticvoidmain(String args[])9b8a8a44dd1c74ae49c20a7cd451974e.png{

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(args.length>0)9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png   port=Integer.parseInt(args[0]);

ecedf933ec37d714bd4c2545da43add2.png  }d18c02628675d0a2c816449d98bda930.pngnewAsyncServer();

ecedf933ec37d714bd4c2545da43add2.png }8f1ba5b45633e9678d1db480c16cae3f.png}4f1150b881333f12a311ae9ef34da474.png

4f1150b881333f12a311ae9ef34da474.png

在当前目录下运行:

javac AsynServer.java

后,若无编译出错,接下来可运行:

java AsynServer  或 java AsynServer ×××(端口号)

上述服务程序在运行时,可指定其侦听端口,否则程序会取8848为默认端口。

2.客户端的简单示例:

4f1150b881333f12a311ae9ef34da474.png4f1150b881333f12a311ae9ef34da474.png//AsyncClient.java

4f1150b881333f12a311ae9ef34da474.png//by zztudou@163.com4f1150b881333f12a311ae9ef34da474.png

4f1150b881333f12a311ae9ef34da474.pngimportjava.nio.channels.SocketChannel;

4f1150b881333f12a311ae9ef34da474.pngimportjava.net.InetSocketAddress;

4f1150b881333f12a311ae9ef34da474.pngimportjava.nio.ByteBuffer;

4f1150b881333f12a311ae9ef34da474.pngimportjava.nio.channels.Selector;

4f1150b881333f12a311ae9ef34da474.pngimportjava.nio.channels.SelectionKey;

4f1150b881333f12a311ae9ef34da474.png

4f1150b881333f12a311ae9ef34da474.pngimportjava.io.IOException;

4f1150b881333f12a311ae9ef34da474.pngimportjava.io.BufferedReader;

4f1150b881333f12a311ae9ef34da474.pngimportjava.io.InputStreamReader;

4f1150b881333f12a311ae9ef34da474.png

1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifclassAsyncClient9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.pngprivateSocketChannel sc;

d18c02628675d0a2c816449d98bda930.pngprivatefinalintMAX_LENGTH=1024;

d18c02628675d0a2c816449d98bda930.pngprivateByteBuffer r_buff=ByteBuffer.allocate(MAX_LENGTH);

d18c02628675d0a2c816449d98bda930.pngprivateByteBuffer w_buff=ByteBuffer.allocate(MAX_LENGTH);

d18c02628675d0a2c816449d98bda930.pngprivatestaticString host ;

d18c02628675d0a2c816449d98bda930.pngprivatestaticintport=8848;

d18c02628675d0a2c816449d98bda930.png 

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifpublicAsyncClient()9b8a8a44dd1c74ae49c20a7cd451974e.png{

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.giftry9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png   InetSocketAddress addr=newInetSocketAddress(host,port);

d18c02628675d0a2c816449d98bda930.png//生成一个socketchanneld18c02628675d0a2c816449d98bda930.pngsc=SocketChannel.open();

d18c02628675d0a2c816449d98bda930.png         

d18c02628675d0a2c816449d98bda930.png//连接到serverd18c02628675d0a2c816449d98bda930.pngsc.connect(addr);

d18c02628675d0a2c816449d98bda930.pngwhile(!sc.finishConnect())

d18c02628675d0a2c816449d98bda930.png    ;  

d18c02628675d0a2c816449d98bda930.png   System.out.println("connection has been established!

9b8a8a44dd1c74ae49c20a7cd451974e.png");

d18c02628675d0a2c816449d98bda930.png    

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifwhile(true)9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png//回射消息d18c02628675d0a2c816449d98bda930.pngString echo;

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.giftry9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png     System.err.println("Enter msg you'd like to send:");

d18c02628675d0a2c816449d98bda930.png     BufferedReader br=newBufferedReader(newInputStreamReader(System.in));

d18c02628675d0a2c816449d98bda930.png//输入回射消息d18c02628675d0a2c816449d98bda930.pngecho=br.readLine();

d18c02628675d0a2c816449d98bda930.png     

d18c02628675d0a2c816449d98bda930.png//把回射消息放入w_buff中d18c02628675d0a2c816449d98bda930.pngw_buff.clear();

d18c02628675d0a2c816449d98bda930.png     w_buff.put(echo.getBytes());

d18c02628675d0a2c816449d98bda930.png     w_buff.flip();

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif    }catch(IOException ioe)9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png     System.err.println("sth. is wrong with br.readline()");

ecedf933ec37d714bd4c2545da43add2.png    }d18c02628675d0a2c816449d98bda930.png  

d18c02628675d0a2c816449d98bda930.png//发送消息d18c02628675d0a2c816449d98bda930.pngwhile(w_buff.hasRemaining())

d18c02628675d0a2c816449d98bda930.png     sc.write(w_buff);

d18c02628675d0a2c816449d98bda930.png    w_buff.clear();    

d18c02628675d0a2c816449d98bda930.png    

d18c02628675d0a2c816449d98bda930.png//进入接收状态d18c02628675d0a2c816449d98bda930.pngRec();

d18c02628675d0a2c816449d98bda930.png//间隔1秒d18c02628675d0a2c816449d98bda930.pngThread.currentThread().sleep(1000);

ecedf933ec37d714bd4c2545da43add2.png   }97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif  }catch(IOException ioe)9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png   ioe.printStackTrace();

ecedf933ec37d714bd4c2545da43add2.png  }97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifcatch(InterruptedException ie)9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png   ie.printStackTrace();

ecedf933ec37d714bd4c2545da43add2.png  }ecedf933ec37d714bd4c2545da43add2.png }d18c02628675d0a2c816449d98bda930.pngd18c02628675d0a2c816449d98bda930.png//读取server端发回的数据,并显示97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifpublicvoidRec()throwsIOException9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.pngintcount;

d18c02628675d0a2c816449d98bda930.png  r_buff.clear(); 

d18c02628675d0a2c816449d98bda930.png  count=sc.read(r_buff);

d18c02628675d0a2c816449d98bda930.png  r_buff.flip();  

d18c02628675d0a2c816449d98bda930.pngbyte[] temp=newbyte[r_buff.limit()];

d18c02628675d0a2c816449d98bda930.png  r_buff.get(temp);

d18c02628675d0a2c816449d98bda930.png  System.out.println("reply is"+count+"long, and content is:"+newString(temp));

ecedf933ec37d714bd4c2545da43add2.png }d18c02628675d0a2c816449d98bda930.png 

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifpublicstaticvoidmain(String args[])9b8a8a44dd1c74ae49c20a7cd451974e.png{

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(args.length<1)9b8a8a44dd1c74ae49c20a7cd451974e.png{//输入需有主机名或IP地址97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.giftry9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png    System.err.println("Enter host name:");

d18c02628675d0a2c816449d98bda930.png    BufferedReader br=newBufferedReader(newInputStreamReader(System.in));

d18c02628675d0a2c816449d98bda930.png    host=br.readLine();

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif   }catch(IOException ioe)9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png    System.err.println("sth. is wrong with br.readline()");

ecedf933ec37d714bd4c2545da43add2.png   }ecedf933ec37d714bd4c2545da43add2.png  }97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifelseif(args.length==1)9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png   host=args[0];

ecedf933ec37d714bd4c2545da43add2.png  }97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifelseif(args.length>1)9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png   host=args[0];

d18c02628675d0a2c816449d98bda930.png   port=Integer.parseInt(args[1]);

ecedf933ec37d714bd4c2545da43add2.png  }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.pngnewAsyncClient();

ecedf933ec37d714bd4c2545da43add2.png }8f1ba5b45633e9678d1db480c16cae3f.png}4f1150b881333f12a311ae9ef34da474.png

4f1150b881333f12a311ae9ef34da474.png

在当前目录下运行:

javac AsynClient.java

后,若无编译出错,确认AsyncServer已经运行的情况下,接下来可运行:

java AsynClient hostname 或 java AsynClient hostname ×××(端口号)

并按提示进行操作即可。

总结

总的来说,用nio进行网络编程还是很有新意的,服务器端软件能在一个线程中维护与众多客户端的通信连接。笔者在本文中试图用一个典型的回射例子说明如何用nio建立最基本的C/S应用。希望大家能试着用用它。

另外,笔者在实践中也发现nio在应用中存在的一些难题,比如如何应用SocketChannel的继承类,以及如何在socketchannel之上应用SSL(Secure Socket Layer)等等,因而希望这篇文章只是抛砖引玉,引起大家对nio作进一步的讨论。

在当前目录下运行:

javac AsynServer.java

后,若无编译出错,接下来可运行:

java AsynServer  或 java AsynServer ×××(端口号)

上述服务程序在运行时,可指定其侦听端口,否则程序会取8848为默认端口。

总结

总的来说,用nio进行网络编程还是很有新意的,服务器端软件能在一个线程中维护与众多客户端的通信连接。笔者在本文中试图用一个典型的回射例子说明如何用nio建立最基本的C/S应用。希望大家能试着用用它。

另外,笔者在实践中也发现nio在应用中存在的一些难题,比如如何应用SocketChannel的继承类,以及如何在socketchannel之上应用SSL(Secure Socket Layer)等等,因而希望这篇文章只是抛砖引玉,引起大家对nio作进一步的讨论。

weixin073智慧旅游平台开发微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
python017基于Python贫困生资助管理系统带vue前后端分离毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值