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

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

2008-03-25 10:27 726 查看
导读:
  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
  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

本文转自
http://www.cn-java.com/www1/?action-viewnews-itemid-1848
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: