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. 计算机应用基础win7作业3答案,电大: 国开计算机应用基础(WIN7)形成性考核册3答案.docx...
  2. 在oracle中怎么判断一个日期是否在一定时间范围内
  3. [html] 举例说明HTML5出来后,有哪些HTML标签被弃用了?
  4. 第四十五期:万亿级日访问量下,Redis在微博的9年优化历程
  5. arduino温湿度计库文件_arduino学习笔记八 温湿度计
  6. PostgreSQL主备切换
  7. minus出错matlab,请求帮忙指点MATLAB中的语法错误
  8. Emacs编辑Nginx
  9. Spring Boot 整合 Kafka 分布式消息系统快速入门
  10. 真正的手机密码大全!(整理完整版)
  11. java项目:基于ssm的高校后勤管理系统(spring+spring mvc+mybatis+easyui+jquery)1004
  12. 中小型企业网络规划设计方案_实战:企业网络系统规划与设计与事项
  13. 离散数学知识点总结(5):蕴含式;命题的推理理论;逻辑推演的方法;推理的有效性证明
  14. 全排列算法(字典序法、SJT Algorithm 、Heap's Algorithm)
  15. 微信开发者工具网页h5本地开发,解决微信公众号绑定域名,本地无法调用微信api问题
  16. 免费在线文档转换工具,一招告诉你超简单.
  17. 【组合逻辑电路】如何从真值表中求解逻辑函数?
  18. Linux学习 day05之用户组权限管理
  19. matlab 柱面投影,图像拼接(不投影到柱面)(渐入渐出融合) matlab程序
  20. coalesce---一个很有用的函数

热门文章

  1. android 伪终端,伪终端pty的原理及使用
  2. 俩台虚拟机,一台有网,一台没网
  3. oracle的口令忘了_Oracle忘记用户名和密码的解决方案
  4. 笔记本计算机忘记密码,Windows笔记本电脑忘记开机登录密码忘记怎么办 最新win7/8/10开机密码重置教程...
  5. 新公司(企业)在各银行开基本户所需资料、流程及费用
  6. TypeScript/JavaScript 2021-02-25T03:34:35.772Z 时区 日期格式化
  7. 基于JAVA成都某4S店销售管理系统计算机毕业设计源码+系统+lw文档+部署
  8. 计算机考试报名不了怎么办,2017年国家公务员考试报名系统繁忙怎么办?
  9. python小游戏扫雷怎么玩的技巧_用 Python 实现扫雷小游戏
  10. MySQL 变量和条件