Java的BIO案例教程

上一节我们对

Socket编程步骤

服务器监听:服务器启动后,它会有一个线程一直启动,等待着客户端端连接。它会定义好自己的端口号。

客户端请求:客户端端套接字提出连接请求,要连接的目标是服务端的套接字。客户端必须要指明服务端套接字的地址和端口号。

连接确认:当服务端收到客户端的连接请求就会响应客户端套接字的请求,建立一个新的线程处理客户端的请求。

案例

我们新建两个 java 项目,一个是服务端,一个是客户端。代码结构如下:

服务端:

客户端:

服务端 BioServer

package net.haicoder.server;

import java.io.*;

import java.net.ServerSocket;

import java.net.Socket;

public class BioServer{

public static void main(String[] args){

int port = 9999;

ServerSocket serverSocket = null;

try {

serverSocket = new ServerSocket(port);

//一直监听,是否有客户端请求过来

while (true) {

Socket socket = serverSocket.accept();

//每次都会新建一个线程,来处理接收到到请求

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

}

} catch (Exception e) {

e.printStackTrace();

} finally {

if (serverSocket != null) {

try {

serverSocket.close();

} catch (IOException e) {

e.printStackTrace();

}

serverSocket = null;

}

}

}

static class SocketHandler implements Runnable{

Socket socket = null;

public SocketHandler(Socket socket){

this.socket = socket;

}

@Override

public void run(){

BufferedReader reader = null;

PrintWriter writer = null;

try {

//读取数据,BIO 是面向流到,所以定义流 BufferedReader 来读取数据

reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));

//将收到的数据返回给客户端

writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));

String readMessage = null;

while (true) {

if ((readMessage = reader.readLine()) == null) {

break;

}

System.out.println("server reading ........" + readMessage);

//将数据返回给客户端

writer.println("server recive : " + readMessage);

writer.flush();

}

} catch (IOException e) {

e.printStackTrace();

} finally {

if (socket != null) {

try {

socket.close();

} catch (IOException e) {

e.printStackTrace();

}

socket = null;

}

if (reader != null) {

try {

reader.close();

} catch (IOException e) {

e.printStackTrace();

}

reader = null;

}

if (writer != null) {

writer.close();

writer = null;

}

}

}

}

}

客户端 BioClient

package net.haicoder.client;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.Socket;

import java.util.Scanner;

public class BioClient{

public static void main(String[] args){

//服务端到 ip 地址

String host = "127.0.0.1";

//和服务端到端口号一致

int port = 9999;

Socket socket = null;

BufferedReader reader = null;

PrintWriter writer = null;

//接收键盘输入数据

Scanner scanner = new Scanner(System.in);

try {

socket = new Socket(host, port);

String message = null;

reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));

writer = new PrintWriter(socket.getOutputStream(), true);

while (true) {

message = scanner.nextLine();

if (message.equals("exit")) {

break;

}

//数据发送服务端

writer.println("客户端输入:" + message);

writer.flush();

System.out.println(reader.readLine());

}

} catch (IOException e) {

e.printStackTrace();

} finally {

if (socket != null) {

try {

socket.close();

} catch (IOException e) {

e.printStackTrace();

}

socket = null;

}

if (reader != null) {

try {

reader.close();

} catch (IOException e) {

e.printStackTrace();

}

reader = null;

}

if (writer != null) {

writer.close();

writer = null;

}

}

}

}

项目启动的时候,我们先启动服务端,再启动客户端。如果先启动客户端,会报连接拒绝异常。因为服务端启动的时候,需要知道服务端的地址和端口号。然后在客户端输入 你好,嗨客网! 效果如下

客户端输出

服务端输出

这样,客户端和服务端就通信了,我们看到服务端和客户端一直没有退出,一直启动着。

伪异步IO

我们知道,伪异步 IO 是将 server 端的线程处理,维护到线程池当中,客户端不会改变,所以我们就改变一下 Server 端的代码即可,代码如下:

package net.haicoder.server;

import java.io.*;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class BioThreadPoolServer{

public static void main(String[] args){

int port = 9999;

ServerSocket serverSocket = null;

ExecutorService service = Executors.newFixedThreadPool(50);

try {

serverSocket = new ServerSocket(port);

//一直监听,是否有客户端请求过来

while (true) {

Socket socket = serverSocket.accept();

//每次都会新建一个线程,来处理接收到到请求

service.execute(new SocketHandler(socket));

}

} catch (Exception e) {

e.printStackTrace();

} finally {

if (serverSocket != null) {

try {

serverSocket.close();

} catch (IOException e) {

e.printStackTrace();

}

serverSocket = null;

}

}

}

static class SocketHandler implements Runnable{

Socket socket = null;

public SocketHandler(Socket socket){

this.socket = socket;

}

@Override

public void run(){

BufferedReader reader = null;

PrintWriter writer = null;

try {

//读取数据,BIO 是面向流到,所以定义流 BufferedReader 来读取数据

reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));

//将收到的数据返回给客户端

writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));

String readMessage = null;

while (true) {

if ((readMessage = reader.readLine()) == null) {

break;

}

System.out.println("server reading ........" + readMessage);

//将数据返回给客户端

writer.println("server recive : " + readMessage);

writer.flush();

}

} catch (IOException e) {

e.printStackTrace();

} finally {

if (socket != null) {

try {

socket.close();

} catch (IOException e) {

e.printStackTrace();

}

socket = null;

}

if (reader != null) {

try {

reader.close();

} catch (IOException e) {

e.printStackTrace();

}

reader = null;

}

if (writer != null) {

writer.close();

writer = null;

}

}

}

}

}

总结

本章节,我们将 socket 的 BIO 编程的客户端和服务端代码编写,将运行效果展示。客户端每输入一次请求,服务端都会处理,然后再回写给客户端。我们也将伪异步 IO 端代码列出。执行效果和 Server 端的代码一样的,有兴趣的同学可以按照上面的代码试一下,找一下感觉。

java io 阻塞io_Java 阻塞IO-Java BIO-嗨客网相关推荐

  1. java 字节流 区别_java字节流字符流区别-嗨客网

    Java字节流与字符流区别 Java字节流与字符流区别教程 我们在 实际上字节流在对文件操作的时候,不会用到缓冲区(内存),对文件本身直接操作而字符流在对文件操作的时候用到了缓冲区,通过缓冲区来对文件 ...

  2. java catch自定义异常_java异常类-java自定义异常-嗨客网

    Java异常类教程 我们在 我们可以看到,在 Exception 表示的是程序中出现了问题,可以直接使用 try - catch 来捕获处理.Error 一般值 Java常见异常 类名 描述 IOEx ...

  3. java基本数据_Java基本数据类型-Java基本数据类型大小-嗨客网

    Java 基本数据类型 序号 数据类型 大小/位 可表示的数据范围 默认值 1 long(长整数) 64 -9223372036854775808-9223372036854775807 0L 2 i ...

  4. java 枚举 color_java 枚举实现方法-java 枚举个性化-嗨客网

    Java枚举自定义方法教程 我们知道枚举是对已知的数据进行穷举,如果每个枚举对象里面有自己独特的操作我们可以让定义的枚举实现一个接口或者在枚举里面定义一个抽象方法. 枚举对象实现自定义方法详解 实现接 ...

  5. java枚举 赋值_java 枚举 - java 枚举构造函数赋值-java 枚举 set 赋值-嗨客网

    Java枚举教程 我们已经了解了 Java枚举详解 语法 [public] enum 枚举类型名称{ 枚举对象1,枚举对象2,枚举对象3...枚举对象n; } 参数 参数 描述 [public] 可选 ...

  6. java 存入对象io_Java面向对象 IO (一)

     Java面向对象  IO  (一) 知识概要: (1)IO概述 (2)IO流的常用基类 (3)IO程序的书写 (4)字符流  写入  读取  文本文件的两种读取方式解析(代码演示) (5)字符流 ...

  7. java while详解_Java while循环-Java while-嗨客网

    Java while教程 在 Java语言while语句详解 语法 while(condition){ //do something } 参数 参数 描述 while while 条件判断关键字 co ...

  8. java date 操作_java日期操作-java Date-java Calendar-嗨客网

    Java日期操作类教程 在生产开发过程中,会用到和时间相关的信息,所以 JavaDate类 说明 Date 类是定义时间对象的一个类,它是一个较为简单的操作类. 案例 package com.haic ...

  9. java非阻塞io流_阻塞式和非阻塞io流初认识

    1  什么是阻塞式和非阻塞式? 阻塞式IO:IO即input/output,阻塞式IO指的是"一旦输入/输出工作没有完成,则程序阻塞,直到输入/输出工作完成".在目前,我们从书本上 ...

最新文章

  1. Javascript鼠标滚轮事件兼容写法
  2. 中小型研发团队架构实践:微服务架构
  3. MVP open day 2009 (二)
  4. PaperNotes(16)-图神经网络GNN简史、不动点建模-笔记
  5. 【离散数学】树的基本概念和结论
  6. php判断服务器操作系统的类型
  7. Vue 单页面应用 把公共组件放在 app.vue 但是我希望某个页面没有这些公共组件怎么办???(比如登陆页面)
  8. webpack跨域问题记录
  9. 1788:Pell数列
  10. mysql之分页查询
  11. python身份证号掩盖出生日期的代码_Python实现第一、二代公民身份证号码有效性校验...
  12. 吴军信息论40讲_刘润对谈吴军:每个人都一定要有数学思维
  13. C++语法知识复习2(黑马程序员教程P109-p146)
  14. JSP入门之表格以及常用表单元素(总结自身编程经验以及多本教科书)
  15. C++程序练习-1008:Maya Calendar-玛雅日历
  16. 灰度拉伸python_对比度拉伸(一些基本的灰度变换函数)基本原理及Python实现
  17. LaTex用模板的时候图片的caption标题无法左对齐
  18. Python对象的浅拷贝与深拷贝
  19. 输入两个正整数,求其最大公约数。
  20. 花呗不小心升级了信用购会影响什么

热门文章

  1. java实现给MultipartFile添加水印
  2. Mybatis传递单个参数
  3. #238 蔡老板分果子 [哈希 or DFS序]
  4. 看完这篇关于电池的高票回答 可防储能大忽悠
  5. 美图进入沪港通、深港通名单,投资它需要了解这三个问题
  6. 5G时代的物联网:福器还是凶器
  7. 浙江临海一民警收到“红牌警告”:立即停止工作
  8. 【Linux 内核 内存管理】memblock 分配器 ③ ( memblock_region 内存块区域 | memblock_region 结构体成员分析 | memblock 分配器标志位 )
  9. 基于生理信号的多模态情绪识别模型
  10. Alfred Workflow 豆瓣插件开发