2、象棋服務主類,接收用戶登錄連接,和用戶的數據處理和轉發:
package sunstudio;
import sunstudio.event.*;
import Java.util.*;
import Java.Net.*;
import Java.io.*;
import sunstudio.util.*;
public class ChessServer implements LoginListener{
int tablecount=20;
ChessTable[] tb=new ChessTable[tablecount];
Hashtable userlist=new Hashtable();
public ServerSocket ss=null;
ChessLogin cl=null;
public static ChessServer hwnd=null;
public static void main(String[] args){
ChessServer server=new ChessServer();
}
public ChessServer(){
for(int i=0;i
19)return;
ChessUser user=(ChessUser)tb[tableID].remove(new Integer(userID));
if(user!=null){
user.tableID=-1;
user.state=-1;
}
}
public boolean addUser(ChessUser user){
if(userlist.contains(new Integer(user.userID)))return false;
userlist.put(new Integer(user.userID),user);
return true;
}
public void removeUser(int userID){
ChessUser user=(ChessUser)userlist.remove(new Integer(userID));
if(user!=null){
user.close();
user=null;
}
}
public void sendToRoom(byte[] h,int l,byte[] d){
for(Enumeration enu=userlist.elements();enu.hasMoreElements();){
try{
((ChessUser)enu.nextElement()).sender.sendData(h,d,l);
}catch(Exception e){}
}
}
public void sendToTable(byte[] h,int l,byte[] d){
for(Enumeration enu=tb[h[3]].elements();enu.hasMoreElements();){
try{
((ChessUser)enu.nextElement()).sender.sendData(h,d,l);
}catch(Exception e){}
}
}
public byte[] getUserListData(){
byte[] ul=new byte[userlist.size()*14];
int ptr=0;
for(Enumeration enu=userlist.elements();enu.hasMoreElements();){
ChessUser user=(ChessUser)enu.nextElement();
System.arraycopy(user.getBytes(),0,ul,ptr,14);
ptr+=14;
}
return ul;
}
public void onUserPackageArrived(byte[] h,int l,byte[] d){
synchronized(this){
try{
int userID=Convert.byteToInt(h[5],h[6],h[7],h[8]);
ChessUser user=null;
user=(ChessUser)userlist.get(new Integer(userID));
switch(h[0]){
case 0://進入游戲桌
//user.setState(h[4]);
System.out.println("用戶"+user.username+"進入"+h[3]+"號游戲桌"+(h[4]%2==0?"執紅":"執黑")+"!");
h[4]=(byte)addTableUser(h[3],userID,h[4]);
break;
case 1:
//user.setState(-1);
System.out.println("用戶"+user.username+"退出"+h[3]+"號游戲桌!");
removeTableUser(h[3],userID);
break;
/////////////////////////////////////
case 2://走步
sendToTable(h,l,d);
return;
case 3://求和
sendToTable(h,l,d);
return;
case 4://認輸
sendToTable(h,l,d);
return;
case 5://悔棋
sendToTable(h,l,d);
return;
/////////////////////////////////////
case 6://用戶列表
break;
case 7://新用戶登錄
break;
case 8://用戶退出
if(user==null)return;
try{
removeTableUser(user.tableID,user.userID);
}catch(Exception ex){ex.printStackTrace();}
try{
removeUser(user.userID);
}catch(Exception exx){exx.printStackTrace();}
System.out.println("用戶退出象棋室");
break;
case 9://聊天信息
sendToTable(h,l,d);
return;
}
sendToRoom(h,l,d);
}catch(Exception e){e.printStackTrace();}
}
}
public void onLoginEvent(LoginEvent evt){
System.out.println(evt.username+","+evt.userID);
ChessUser user=new ChessUser(evt.username,evt.userID,evt.socket);
if(user.init()){
System.out.println("用戶進入象棋室");
sendToRoom(new byte[]{7,14,0,0,0,0,0,0,0,0,0,0},14,user.getBytes());//新用戶登錄
if(addUser(user)){
user.start();
try{
user.sender.sendUserListData(getUserListData());
}catch(Exception e){}
}
}
//else銷毀用戶對象
}
}
3、象棋用戶類,實現用戶信息的存儲和用戶數據的接收和轉發:
package sunstudio;
import Java.Net.*;
import Java.io.*;
import sunstudio.Netlib.*;
import sunstudio.util.*;
public class ChessUser implements TcpDataListener{
public String username=null;
public int userID=-1,tableID=-1;
public int state=-1;//0:執紅走棋1:執黑走棋2:看紅走棋3:看黑走棋
byte[] data=new byte[14];
Socket socket=null;
TcpDataReceiver receiver=null;
TcpDataSender sender=null;
public ChessUser(String un,int ui,Socket st){
username=un;
userID=ui;
socket=st;
System.arraycopy(username.getBytes(),0,data,0,Math.min(8,username.getBytes().length));
System.arraycopy(Convert.intToBytes(ui),0,data,8,4);
data[12]=(byte)-1;
data[13]=(byte)-1;
}
public boolean init(){
try{
sender=new TcpDataSender(socket.getOutputStream());
receiver=new TcpDataReceiver(socket.getInputStream());
receiver.addTcpDataListener(this);
return true;
}catch(IOException e){}
return false;
}
public void setState(int stat){
state=stat;
data[13]=(byte)stat;
}
public void start(){
try{
sender.sendLoginBack(userID);
receiver.start();
}catch(Exception e){}
}
public void onTcpDataArrived(TcpDataEvent evt){
ChessServer.hwnd.onUserPackageArrived(evt.getHeader(),evt.getDataLen(),evt.getData());
}
public byte[] getBytes(){
return data;
}
public void close(){
try{
if(socket!=null){
socket.close();
socket=null;
}
}catch(Exception e){}
try{
if(receiver!=null){
receiver.setRunning(false);
receiver=null;
}
}catch(Exception e){}
try{
if(sender!=null)sender=null;
}catch(Exception e){}
}
}
4、TCP數據接收器:
package sunstudio.Netlib;
import Java.util.*;
import Java.Net.*;
import Java.io.*;
import sunstudio.util.*;
public class TcpDataReceiver extends Thread{
Vector listeners=new Vector();
boolean isrunning=true;
InputStream is=null;
byte[] h=new byte[12];
byte[] d=new byte[1024];
int l=0;
public TcpDataReceiver(InputStream s){
is=s;
}
public void run(){
try{
while(isrunning){
HttpInputStream.readBytes(is,12,h);
l=Convert.byteToShort(h[1],h[2]);
if(l>0)HttpInputStream.readBytes(is,l,d);
if(l>0)notifyListeners(h,l,d);
else if(l==0)notifyListeners(h,0,null);
else throw new IOException();
}
}catch(IOException e){
System.out.println("讀取流數據異常!");
//異常處理,關閉socket
}
}
public void addTcpDataListener(TcpDataListener hrl){
listeners.addElement(hrl);
}
synchronized void notifyListeners(byte[] hh,int ll,byte[] dd){
TcpDataEvent evt=new TcpDataEvent(hh,ll,dd);
for(Enumeration enumeration=listeners.elements();enumeration.hasMoreElements();((TcpDataListener)enumeration.nextElement()).onTcpDataArrived(evt));
}
public void setRunning(boolean rr){
this.isrunning=rr;
}
}
5、TCP數據監聽接口:
package sunstudio.Netlib;
public interface TcpDataListener{
public void onTcpDataArrived(TcpDataEvent evt);
}
6、TCP數據包接收事件:
package sunstudio.Netlib;
import Java.Net.*;
public class TcpDataEvent{
byte[] head=null;
int datalen=-1;
byte[] datas=null;
public TcpDataEvent(byte[] h,int len,byte[] dt){
head=h;
datalen=len;
datas=dt;
}
public byte[] getHeader(){
return head;
}
public byte[] getData(){
return datas;
}
public int getDataLen(){
return datalen;
}
}
7、TCP數據發送器:
package sunstudio.Netlib;
import Java.io.*;
import sunstudio.util.*;
public class TcpDataSender{
OutputStream os;
byte[] d=new byte[1024];
int l;
public TcpDataSender(OutputStream ost){
os=ost;
}
public void sendLoginBack(int userID){
byte[] cd=new byte[9];
System.arraycopy(Convert.intToBytes(userID),0,cd,2,4);
sendeHeader((byte)10,cd);
}
public void sendeHeader(byte cmdType,byte[] cData){
try{
d[0]=cmdType;//登錄
System.arraycopy(Convert.shortToBytes((short)0),0,d,1,2);
System.arraycopy(cData,0,d,3,9);
os.write(d,0,12);
os.flush();
}catch(Exception e){}
}
public void sendUserListData(byte[] ud){
byte[] hh=new byte[12];
hh[0]=6;
System.arraycopy(Convert.shortToBytes((short)ud.length),0,hh,1,2);
sendData(hh,ud,ud.length);
}
public void sendData(byte[] hh,byte[] dd,int ln){
try{
os.write(hh);
os.write(dd,0,ln);
}catch(Exception e){}
}
}
8、數據接收類(保證讀取TCP字節數組數據長度正確)
package sunstudio.util;
import Java.io.*;
public class HttpInputStream extends InputStream{
InputStream is=null;
public HttpInputStream(InputStream is1){
is=is1;
}
public int read() throws IOException{
return is.read();
}
public String readLine() throws IOException{
ByteArrayOutputStream b=new ByteArrayOutputStream();
int c;
while((c=read())!=-1){
if(c==10)break;
else b.write(c);
}
if(c==-1)return null;
if(b.size()==1){
if(b.toByteArray()[0]==13)return "";
}
return new String(b.toByteArray(),0,b.size()-1);
}
public static void readBytes(InputStream inputStream,int length,byte[] data) throws IOException{
if(length==0)return;
int n=0;
int read=0;
do{
read=inputStream.read(data,n,length-n);
n+=read;
if(n==-1)throw new IOException("網絡連接異常斷開,讀取數據異常");
}while(n
}
}
(待續。。。)如有問題請和我聯系[[email protected]]