导读:
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
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