前言
目前流行的NIO網絡框架,有netty.mina.我用過一段時間netty,感覺有點爽。由於框架主程已經寫好了,我只需要在上面做開發,所以幾乎不用太底層的東西,就可以輕鬆上手。往往遇到一些真正的問題時,就需要去了解下整個框架了。下面我從最基礎BIO的開始瞭解。
一、BIO 一個服務器與多客戶端進行通信時,產生的線程個數是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.Clientpackage 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);
}
}
}
}
}
運行:
Server Start .
###########################################
[2015-9-12 15:29:02] 編號 2049638772 request#1
Client
recive data from server : [2015-9-12 15:29:02] : 恭喜你抽到了屠龍刀