前言
目前流行的NIO网络框架,有netty.mina.我用过一段时间netty,感觉有点爽。由于框架主程已经写好了,我只需要在上面做开发,所以几乎不用太底层的东西,就可以轻松上手。往往遇到一些真正的问题时,就需要去了解下整个框架了。下面我从最基础BIO的开始了解。
一、BIO 一个服务器与多客户端进行通信时,产生的线程个数是1:1.
二、服务端如何处理客服端发来的请求.
三、代码实现
1.连接管道
package com;
/**
* 抽象连接管道
* @author xuan.lei
*
*/
public interface IChannel {
void write(String msg);
String read();
}
package com.domain;
public enum Code {
PLYAER_PACKGE(1,"玩家背包"),
PLAYER_LOTTERY(3,"玩家抽奖"),
ENTER_MISSION(2,"进入副本");
private int id;
private String desc;
private Code(int id, String desc) {
this.id = id;
this.desc = desc;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
3.Client
package com.domain;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Calendar;
import com.IChannel;
public class Client implements IChannel,Runnable {
private String name;
private Socket socket;
PrintWriter out = null;
BufferedReader in=null;
public Client( String name) {
super();
this.name = name;
}
public boolean connect(String host,int port){
try {
socket = new Socket(host,port);
out = new PrintWriter(socket.getOutputStream(),true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
return true;
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
}
return false;
}
public void close(){
try {
out.close();
in.close();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public boolean isClosed(){
return socket.isConnected();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
@Override
public void write(String msg) {
out.println("["+Calendar.getInstance().getTime().toLocaleString()+"] " +name+" request#"+msg);
}
@Override
public String read() {
try {
if(in.ready()){
String body = in.readLine();
return "recive data from server : "+body;
}
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("与服务端失去连接");
}
return "";
}
@Override
public void run() {
while(true){
String readMsgFromServer = read();
if(!"".equals(readMsgFromServer)){
System.out.println(readMsgFromServer);
}else {
//System.out.println("服务器无响应.");
}
}
}
}
4.服务器处理类
package com.domain;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Calendar;
import com.IChannel;
public class ServerHandler implements IChannel,Runnable {
private Socket socket;
private boolean isSocketActive;
PrintWriter out=null;
BufferedReader in = null;
public ServerHandler(Socket socket, boolean isSocketActive) {
super();
this.socket = socket;
this.isSocketActive = isSocketActive;
}
@Override
public void run() {
try {
out = new PrintWriter(socket.getOutputStream(),true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true){
String readMsgFromClient = read();
if(!"".equals(readMsgFromClient)){
System.out.println(readMsgFromClient);
int codeIndex = readMsgFromClient.indexOf("#");
int code = Integer.valueOf(readMsgFromClient.substring(codeIndex+1));
switch(Code.values()[code]){
case PLAYER_LOTTERY:
write("恭喜你抽到了屠龙刀");
break;
case PLYAER_PACKGE:
write("已打开玩家背包");
break;
case ENTER_MISSION:
write("已进入副本.");
break;
default:
out.println("当前命令没有注册。");
break;
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
out.close();
try {
socket.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public void write(String msg) {
out.println("["+Calendar.getInstance().getTime().toLocaleString()+"] "+" : "+msg);
}
@Override
public String read() {
try {
if(in.ready()){
return in.readLine();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
}
5.服务器
package com;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import com.domain.ServerHandler;
public class ChatServer {
public static void main(String args[]) throws IOException{
ServerSocket server = new ServerSocket(9000);
System.out.println("###########################################");
System.out.println("Server Start .");
System.out.println("###########################################");
while(true){
Socket accept = server.accept();
new Thread(new ServerHandler(accept, true)).start();
}
}
}
6.玩家
package com;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Random;
import com.domain.Client;
public class Player{
public static void main(String args[]) throws IOException {
Client client = new Client("编号 "+new Random(System.currentTimeMillis()).nextInt());
BufferedReader in=null;
in = new BufferedReader(new InputStreamReader(System.in));
if(client.connect("127.0.0.1", 9000)){
new Thread(client).start();
while(true){
String readMsgFromConsole = in.readLine();
if(!readMsgFromConsole.equals("")){
client.write(readMsgFromConsole);
}
}
}
}
}
运行:
Sever
###########################################
Server Start .
###########################################
[2015-9-12 15:29:02] 编号 2049638772 request#1
Client
Server Start .
###########################################
[2015-9-12 15:29:02] 编号 2049638772 request#1
Client
1
recive data from server : [2015-9-12 15:29:02] : 恭喜你抽到了屠龙刀
recive data from server : [2015-9-12 15:29:02] : 恭喜你抽到了屠龙刀