java网络编程系列之JavaIO的“前世”:BIO阻塞模型
Posted 大忽悠爱忽悠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java网络编程系列之JavaIO的“前世”:BIO阻塞模型相关的知识,希望对你有一定的参考价值。
java网络编程系列之JavaIO的“前世”:BIO阻塞模型
Scoket与ServerSocket
-
bind
:提供给ServerSocket
端口进行绑定操作,客户端只需要向指定的端口发送数据,服务器就可以收到数据 -
accept
: 阻塞式调用,等待客户端与其建立连接,如果没有客户端与其建立连接,那么accept
函数就会阻塞住当前线程 -
connect
:客户端socket
通过指定的服务器的主机和端口,与指定的服务器进程相连接 - 一旦服务器的
accept
函数,接收了对应的客户端连接,便会返回一个socket
对象,就是服务器进程和指定客户端进行通信的一个端点 - 连接建立成功后,变可以通过I/O流进行数据的传输
- 当数据传输完毕后,客户端调用close函数,关闭对应的端点,服务器端如果此时尝试向客户端发送数据,便会抛出异常,因此服务器端也应该关闭端点
服务器端: ServerSocket代码实战
public class Server
public static void main(String[] args)
final int DEFAULT_PORT=8080;
ServerSocket serverSocket=null;
try
//监听端口
serverSocket=new ServerSocket(DEFAULT_PORT);
System.out.println("服务器启动,监听端口为: "+DEFAULT_PORT);
//与客户端进行数据交换
while(true)
//等待客户端连接--这里会阻塞住,知道有客户端连接
Socket socket = serverSocket.accept();
System.out.println("客户端["+socket.getPort()+"]已连接");
//获取客户端的输入数据流
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//获取向客户端写入数据流
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//读取客户端发送的消息
String line = br.readLine();
if(line!=null)
System.out.println("客户端["+socket.getPort()+"]发送的消息:"+line);
//向客户端写入数据
bw.write("服务器: "+line+"\\n");
//刷新缓冲区的数据,确保全部写入
bw.flush();
catch (IOException e)
e.printStackTrace();
finally
//关闭流---也可以用try with resources
if(serverSocket!=null)
try
serverSocket.close();
System.out.println("关闭服务端的serverSocket");
catch (IOException e)
e.printStackTrace();
客户端: socket代码实战
//客户端
public class Client
public static void main(String[] args)
//服务器的主机地址
final String DEFAULT_SERVER_HOST="127.0.0.1";
//服务器的端口
final int DEFAULT_SERVER_PORT=8080;
Socket socket=null;
BufferedWriter bw = null;
try
//创建sokcet
socket=new Socket(DEFAULT_SERVER_HOST,DEFAULT_SERVER_PORT);
//创建IO流
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//让用户输入信息
BufferedReader consoleBr=new BufferedReader(new InputStreamReader(System.in));
String input=consoleBr.readLine();
//发送消息给服务器
bw.write(input+"\\n");
bw.flush();
//读取服务器返回的消息
String line = br.readLine();
System.out.println(line);
catch (IOException e)
e.printStackTrace();
finally
//关闭最外层的writer,会自动去flush缓冲区里面的剩余内容
//关闭writer,也就关闭了socket
if(bw!=null)
try
bw.close();
System.out.println("关闭客户端的socket");
catch (IOException e)
e.printStackTrace();
运行简单的服务器客户端实例
补充知识点 > 1 — 多重流嵌套(比如BufferedWrite)时各个流的关闭问题
public
class FilterOutputStream extends OutputStream
protected OutputStream out;
public FilterOutputStream(OutputStream out)
this.out = out;
public void flush() throws IOException
out.flush();
public void close() throws IOException
try
flush();
catch (IOException ignored)
out.close();
这是jdk1.6 中FilterOutputStream流的部分实现代码(我是粘贴过来的)。从这段代码可以看出,嵌套流关闭时直接关闭的是被封装流,只是在关闭之前flush。
因此关闭最外层的流即可
也可以考虑使用try with resource 关闭流
public static void main(String[] args)
try (FileInputStream inputStream = new FileInputStream(new File("test")))
System.out.println(inputStream.read());
catch (IOException e)
throw new RuntimeException(e.getMessage(), e);
优化
上面的例子中,客户端发送一次数据给服务器端后,便会自动断开连接,这样显然不太好,所以我们下面进行了优化
//客户端
public class Client
public static void main(String[] args)
//服务器的主机地址
final String DEFAULT_SERVER_HOST="127.0.0.1";
//服务器的端口
final int DEFAULT_SERVER_PORT=8080;
//停止
final String QUIT="quit";
Socket socket=null;
BufferedWriter bw = null;
try
//创建sokcet
socket=new Socket(DEFAULT_SERVER_HOST,DEFAULT_SERVER_PORT);
//创建IO流
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//让用户输入信息
BufferedReader consoleBr=new BufferedReader(new InputStreamReader(System.in));
String input=null;
while(!QUIT.equals(input=consoleBr.readLine()))
//发送消息给服务器
bw.write(input+"\\n");
bw.flush();
//读取服务器返回的消息
String line = br.readLine();
System.out.println(line);
catch (IOException e)
e.printStackTrace();
finally
//关闭最外层的writer,会自动去flush缓冲区里面的剩余内容
//关闭writer,也就关闭了socket
if(bw!=null)
try
bw.close();
System.out.println("关闭客户端的socket");
catch (IOException e)
e.printStackTrace();
public class Server
public static void main(String[] args)
final int DEFAULT_PORT=8080;
ServerSocket serverSocket=null;
try
//监听端口
serverSocket=new ServerSocket(DEFAULT_PORT);
System.out.println("服务器启动,监听端口为: "+DEFAULT_PORT);
//等待客户端连接--这里会阻塞住,知道有客户端连接
Socket socket = serverSocket.accept();
System.out.println("客户端["+socket.getPort()+"]已连接");
//获取客户端的输入数据流
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//获取向客户端写入数据流
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//读取客户端发送的消息
String line=null;
//与客户端进行数据交换
while((line = br.readLine())!=null)
System.out.println("客户端["+socket.getPort()+"]发送的消息:"+line);
//向客户端写入数据
bw.write("服务器: "+line+"\\n");
//刷新缓冲区的数据,确保全部写入
bw.flush();
catch (IOException e)
e.printStackTrace();
finally
//关闭流---也可以用try with resources
if(serverSocket!=null)
try
serverSocket.close();
System.out.println("关闭服务端的serverSocket");
catch (IOException e)
e.printStackTrace();
以上是关于java网络编程系列之JavaIO的“前世”:BIO阻塞模型的主要内容,如果未能解决你的问题,请参考以下文章
javaio流之字节输入流:java.io.InputStream类及子类java.io.FileInputStream