您的位置:首页 > 理论基础 > 计算机网络

如何用Java实现网络中国象棋室(二)

2008-05-23 18:49 483 查看
google_ad_client = "pub-8800625213955058";

/* 336x280, 创建于 07-11-21 */

google_ad_slot = "0989131976";

google_ad_width = 336;

google_ad_height = 280;

//

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;i19)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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: