网络编程基本都是使用的Client/server模型,也就是两个进程之间相互通信。服务端提供IP和端口,客户端通过连接操作向服务端监听的地址发起连接请求,通过三次握手建立连接,连接成功就可以用Socket通信(ServerSocke负责绑定IP,启动监听端口,socket发起连接,连接成功后,通过IO流进行同步阻塞通信)。
今天以一个TimeServer回顾
直接上代码
package BIO;
/**
* Created by zhangguanlong on 2017/12/28.
*/
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class TimeServer {
public static void main(String[] args) throws IOException {
int port = 8380;
if (args != null&& args.length>0) {
port=Integer.valueOf(args[0]);
}
ServerSocket server = null;
try {
server= new ServerSocket(port);
System.out.println("The time server is start on port:"+port);
Socket socket =null;
while (true) {
socket=server.accept();
new Thread(new TimeServerHandler(socket)).start();
}
} catch (Exception e) {
// TODO: handle exception
}finally {
if (server != null) {
System.out.println("The time server close");
server.close();
server = null;
}
}
}
}
通过死循环监听客户端的连接,如果没有客户端接入。就会阻塞在ServerSocket的accept上
不信请看堆栈信息
"main" #1 prio=5 os_prio=0 tid=0x0000000002ae2800 nid=0x2624 runnable [0x0000000002adf000]
java.lang.Thread.State: RUNNABLE
at java.net.DualStackPlainSocketImpl.accept0(Native Method)
at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:131)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:404)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:199)
- locked <0x00000000d5cb7918> (a java.net.SocksSocketImpl)
at java.net.ServerSocket.implAccept(ServerSocket.java:545)
at java.net.ServerSocket.accept(ServerSocket.java:513)
at BIO.TimeServer.main(TimeServer.java:22)
Locked ownable synchronizers:
- None
有接入的时候构造TimeServerHandler对象,这是一个Runnerable
package BIO;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Date;
import java.net.Socket;
/**
* Created by zhangguanlong on 2017/12/28.
*/
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) {
body=in.readLine();
if (body==null)
break;
System.out.println("the time server recieved order:"+body);
currentTime = "Query TIME ORDER".equalsIgnoreCase(body)?new Date(System.currentTimeMillis()).toString():"BAD ORDER";
out.println(currentTime);
}
} catch (Exception e) {
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 BIO;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* Created by zhangguanlong on 2017/12/28.
*/
public class TimeClient {
public static void main(String[] args) {
int port = 8380;
if (args == null&&args.length>0) {
port = Integer.valueOf(args[0]);
}
Socket socket = null;
BufferedReader in =null;
PrintWriter out = null;
try {
socket =new Socket("127.0.0.1",port);
in =new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()),true);
out.println("Query TIME ORDER");
System.out.println("send order 2 server succeed.");
String res = in.readLine();
System.out.println("Now is"+res);
} catch (IOException e) {
e.printStackTrace();
}finally {
if (in != null) {
try {
in.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if (out !=null) {
out.close();
out=null;
}
if (socket==null) {
try {
socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
socket=null;
}
}
}
}
运行结果