网络编程的基本模型是Client/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信息(绑定的IP地址和监听端口),客户端通过连接操作向服务端监听的地址发起连接请求,通过三次握手建立连接,如果连接建立成功,双方就可以通过网络套接字(Socket)进行通信。
采用BIO通信模型的服务器端,通常由一个独立的Acceptor线程负责监听客户端的连接,它接收到客户端连接成功请求之后为每个客户端创建一个新的线程进行链路请求,处理完成之后,通过输出流返回应答给客户端,最后销毁线程。
下面通过一个简单的例子,来模拟BIO
例子是一个简单的Server和Client一应一答
package com.hueason.netty.n1.bio;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* Created by Administrator on 2017/4/7.
*/
public class TimeServer {
public static void main(String[] args) throws IOException {
int port = 8080;
if(args != null && args.length > 0){
try {
Integer.valueOf(args[0]);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
ServerSocket server = null;
try {
server = new ServerSocket(port);
System.out.println("The time server is start in port :"+port);
Socket socket = null;
while (true){
System.out.println("while true");
socket = server.accept();
System.out.println("accept");
new Thread(new TimeServerHandler(socket)).start();
}
}finally {
if(server != null){
System.out.println("The time server close");
server.close();
server = null;
}
}
}
}
package com.hueason.netty.n1.bio;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Date;
/**
* Created by Administrator on 2017/4/7.
*/
public class TimeServerHandler implements Runnable {
private Socket socket;
public TimeServerHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
out = new PrintWriter(this.socket.getOutputStream(),true);
String currentTime = null;
String body = null;
while (true){
System.out.println("handler while true");
System.out.println(in);
body = in.readLine();
System.out.println("[[[");
System.out.println("body "+body);
if(body == null){
break;
}
System.out.println("The time server receive order :"+ body);
currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body)?new Date(System.currentTimeMillis()).toString():"BAD ORDER";
out.println(currentTime);
}
}catch (Exception e){
e.printStackTrace();
if(in != null){
try {
in.close();
} catch (IOException e1) {
e1.printStackTrace();
}
if(out != null){
out.close();
out = null;
}
if(this.socket != null){
try {
this.socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
this.socket = null;
}
}
}
}
}
package com.hueason.netty.n1.bio;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
* Created by Administrator on 2017/4/18.
*/
public class TimeClient {
public static void main(String[] args) {
int port = 8080;
if (args != null && args.length > 0) {
port = Integer.valueOf(args[0]);
}
Socket socket = null;
BufferedReader in = null;
PrintWriter out = null;
System.out.println(port);
try {
socket = new Socket("127.0.0.1", port);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
out.println("QUERY TIME ORDER");
System.out.println("Send order 2 server succeed.");
String resp = in.readLine();
System.out.println("Now is :" + resp);
} catch (Exception e) {
} finally {
if (out != null) {
out.close();
out = null;
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
in = null;
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
socket = null;
}
}
}
}
简单的逻辑就是Server监听8080端口,接收到客户端的查询时间请求就返回当前时间
先运行Server在运行Client,client端打印当前时间
BIO主要的问题在于每当有一个新的客户端请求接入时,服务端必须创建一个新的线程处理新接入的客户端链路,一个线程只能处理一个客户端连接。
这种模型无法满足高并发需求