目录
一、同步阻塞(BIO)
发送方发送请求之后一直等待响应。 接收方处理请求时进行的IO操作如果不能马上等到返回结果,就一直等到返回结果后,才响应发送方,期间不能进行其他工作。
代码:
sever端
public class BIOClient {
private Socket socket;
private Scanner scanner;
private final int port = 5676;
private final String IP = "127.0.0.1";
private BufferedWriter writer;
private BufferedReader reader;
private OutputStream outputStream;
private InputStream inputStream;
private volatile boolean flag = true;
public BIOClient() {
scanner = new Scanner(System.in);
try {
socket = new Socket(IP, port); //请求和服务器建立连接
//TCP三次握手的起点 只要这个socket 建立成功说明连接建立成功
} catch (IOException e) {
e.printStackTrace();
}
}
public void startClient() {
try {
boolean closed = socket.isClosed();
if (!closed) {
outputStream = socket.getOutputStream();//负责发送消息
inputStream = socket.getInputStream();// 负责接收消息
writer = new BufferedWriter(new OutputStreamWriter(outputStream));
reader = new BufferedReader(new InputStreamReader(inputStream));
new Thread(new SendThread()).start();
while (flag) {
String str = reader.readLine();
System.out.println("接受到服务器的信息为 : " + str);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
inputStream.close();
outputStream.close();
reader.close();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class SendThread implements Runnable {
@Override
public void run() {
while (true) {
System.out.println("请输入回复信息:");
String s = scanner.nextLine();
try {
writer.write(s + "\n");
writer.flush();
if (s.equals("exit")) {
flag = false;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
client端
//TCP协议代码
public class BIOServer {
private ServerSocket socket;//开发TCP的工具包
private final int port = 5676;
public BIOServer() {
try {
//将服务器绑定到特定端口上
socket = new ServerSocket(port);
} catch (IOException e) {
e.printStackTrace();
}
}
public void startTCPServer() {
//接收客户端的请求
try {
while (true) { //不停的接收客户端请求
Socket clientSocket = socket.accept(); //阻塞方法 阻塞到连接建立上为止
//TCP 建立连接 三次握手 三次握手的终点
// clientSocket请求连接的用户一一对应
//后面讲使用该clientSocket进行和这个用户之间的通信
new Thread(new ServerHandler(clientSocket)).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
二、同步非阻塞
发送方发送请求之后,一直等待响应。 接受方处理请求时进行的IO操作如果不能马上的得到结果,就立即返回,取做其他事情。 但是由于没有得到请求处理结果,不响应发送方,发送方一直等待。 当IO操作完成以后,将完成状态和结果通知接收方,接收方再响应发送方,发送方才进入下一次请求过程。(实际不应用)
三、I/O复用(NIO)
I0多路复用的好处就在于单个进程就可以同时处理多个网络连接的I0。它的基本原理就是不再由应用程序自己监视连接,取而代之由内核替应用程序监视文件描述符。
1.selector
Selector称为选择器,当然你也可以翻译为多路复用器。它是Java NIO核心组件中的-个,用于检查-个或多个NIO Channel (通道)的状态是否处于可读、可写。Selector 提供选择已经就绪的任务的能力: Selector 会不断检测注册在其上的Channel,如果某个Channel.上面发生读或者写事件,这个Channel就处于就绪状态,会被Selector轮询出来,然后通做出相对应的操作。
2.channel
channel用户I0操作的连接,由java.nio.channels包定义,原有I0的一-种补充,但是不能直接访问数据需要和缓冲区Buffer进行交互。与Selector - -起使用时,Channel 必须处于非阻塞模式下。
NIO服务器端:
public class NIOServer {
private int port = 5676;
private ServerSocketChannel serverChannel;
private FileChannel fileChannel;
// private Selector selector;
private ByteBuffer recBuffer;
private ByteBuffer sendBuffer;
public NIOServer() {
try {
serverChannel = ServerSocketChannel.open();
serverChannel.bind(new InetSocketAddress(port));
recBuffer = ByteBuffer.allocate(1024);
sendBuffer = ByteBuffer.allocate(1024);
fileChannel = FileChannel.open(Paths.get(
"D:\\tmp\\one\\two\\three\\channel.txt"),
StandardOpenOption.WRITE, StandardOpenOption.CREATE);
} catch (IOException e) {
e.printStackTrace();
}
}
public void startNIOServer() throws IOException {
SocketChannel socketChannel = serverChannel.accept();
while (socketChannel.read(recBuffer) != -1) {//read一直阻塞等待客户端传输数据
recBuffer.flip();
fileChannel.write(recBuffer);
recBuffer.clear();
}
//接受客户端的数据
//给客户端回复信息
sendBuffer.put("服务器已经接收到文件".getBytes());
sendBuffer.flip();
socketChannel.write(sendBuffer);
socketChannel.close();
fileChannel.close();
serverChannel.close();
}
}
handler
public class ServerHandler implements Runnable {
private Socket clientSocket;
private BufferedWriter writer;
private BufferedReader reader;
private OutputStream outputStream;
private InputStream inputStream;
private Scanner scanner;
public ServerHandler(Socket clientSocket) {
scanner = new Scanner(System.in);
this.clientSocket = clientSocket;
try {
outputStream = clientSocket.getOutputStream();//负责发送消息
inputStream = clientSocket.getInputStream();// 负责接收消息
//字节转字符的过程
//文件传输
// BufferedOutputStream outputStream1 = new BufferedOutputStream(outputStream);
writer = new BufferedWriter(new OutputStreamWriter(outputStream));
reader = new BufferedReader(new InputStreamReader(inputStream));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
while (true) {
String str = reader.readLine();
System.out.println("接受到客户端的信息为 : " + str);
if (str.equals("exit")) {
break;
}
System.out.println("请输入回复信息:");
String s = scanner.nextLine();
writer.write(s + "\n");
writer.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
outputStream.close();
reader.close();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
客户端:
public class NIOClient {
private int port = 5676;
private SocketChannel socketChannel;
private FileChannel fileChannel;
// private Selector selector;
private ByteBuffer recBuffer;
private ByteBuffer sendBuffer;
public NIOClient() {
try {
socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", port));
recBuffer = ByteBuffer.allocate(1024);
sendBuffer = ByteBuffer.allocate(1024);
fileChannel = FileChannel.open(Paths.get(
"D:\\tmp\\one\\two\\three\\Newchannel.txt"),
StandardOpenOption.READ, StandardOpenOption.CREATE);
} catch (IOException e) {
e.printStackTrace();
}
}
public void startClient() throws IOException {
while (fileChannel.read(sendBuffer) != -1) {
sendBuffer.flip();
socketChannel.write(sendBuffer);
sendBuffer.clear();
}
//等待接收服务器的回值
int len = -1;
while ((len = socketChannel.read(recBuffer)) != -1) {
System.out.println(new String(recBuffer.array(), 0, len));
recBuffer.clear();
}
}
四、信号I/O
允许Socket进行信号驱动I0,并注册一-个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到- -个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。
五、异步非阻塞(AIO)
发送方发送请求之后,一直等待响应。 接受方处理请求时进行的IO操作如果不能马上的得到结果,就立即返回,取做其他事情。 但是由于没有得到请求处理结果,不响应发送方,发送方一直等待。 当IO操作完成以后,将完成状态和结果通知接收方,接收方再响应发送方,发送方才进入下一次请求过程。(实际不应用)