文章目录
一、IO实现
1.1 传统IO的特点
- 代码执行时会存在两个阻塞点
server.accept(); 等待链接
inputStream.read(bytes); 等待输入
- 单线程情况下只能为一个客户端服务;
- 用线程池可以有多个客户端连接,但是非常消耗性能;
- 使用传统的I/O程序读取文件内容, 并写入到另一个文件(或Socket), 如下程序:
File.read(fileDesc, buf, len);
Socket.send(socket, buf, len);
会有较大的性能开销, 主要表现在一下两方面:
上下文切换(context switch), 此处有4次用户态和内核态的切换;
Buffer内存开销, 一个是应用程序buffer, 另一个是系统读取buffer以及socket buffer;
1.2 项目实现
1.创建两个Java项目
2.分别创建两个类,Server和Client
3.编写代码
Server服务端:
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException{
//创建客户端的Socket对象(SevereSocket)
//ServerSocket (int port)创建绑定到指定端口的服务器套接字
ServerSocket serverSocket=new ServerSocket(6000);
//Socket accept()侦听要连接到此套接字并接受它
Socket socket=serverSocket.accept();
//获取输入流,读数据,并把数据显示在控制台
InputStream inputStream=socket.getInputStream();
byte[] bytes=new byte[1024];
int len=inputStream.read(bytes);
String data=new String(bytes,0,len);
System.out.println("数据是:"+data);
//释放资源
socket.close();
serverSocket.close();
}
}
Client客户端:
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException{
//创建客户端的Socket对象
//Socket (InetAddress adress,int port)创建流套接字并将其连接到指定IP地址的指定端口号
//Socket (String host,int port)创建流套接字并将其连接到指定主机的指定端口号
Socket s=new Socket("192.168.0.102", 6000);
//获取输出流,写数据
//OutputStream getOutputStream();返回此套接字的输出流
OutputStream os=s.getOutputStream();
os.write("你好,服务器端!".getBytes());
//释放资源
s.close();
}
}
1.3 结果
二、NIO实现
2.1NIO特点
- NIO在单线程下可以同时为多个客户端服务
- NIO技术省去了将操作系统的read buffer拷贝到程序的buffer, 以及从程序buffer拷贝到socket buffer的步骤, 直接将 read buffer 拷贝到 socket buffer. java 的 FileChannel.transferTo() 方法就是这样的实现, 这个实现是依赖于操作系统底层的sendFile()实现的.
public void transferTo(long position, long count, WritableByteChannel target);
它的底层调用的是系统调用sendFile()方法
sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
2.2 IO与NIO的差别
具体参考:Netty入门(一)——传统IO与NIO比较(一)
2.3 项目实现
1.同样新建两个Java项目
2.分别建一个Server类和Client类
Server服务器端:
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util