?? socketmanager.java
字號:
package com.tianxia.qipai.model.socket;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.util.Timer;
import javax.microedition.io.ConnectionNotFoundException;
import javax.microedition.io.Connector;
import javax.microedition.io.Datagram;
import javax.microedition.io.DatagramConnection;
import com.tianxia.qipai.model.util.*;
public class SocketManager extends Thread { //socket連接的維護實現(xiàn)
private String ipstring;
private String recpacket;
private static SocketInterface socketinterface;
long now,recent,datarecent,gcrecent; //now 表示當前時間,recent表示最近一次socket連接的時間
private boolean datasendflag;
private static SocketManager instance;
private DatagramConnection dc;
private boolean Ifthreadstart; //線程啟動標志
private boolean connectflag;
private boolean toconnectflag;
private boolean havesenddata;
private boolean switchstate; //是否正在切換服務器
private int currcount; //連接維護調用次數(shù)
private boolean runflag = true;
private String senddata;
private final static int MAXCOUNT = 3;//socket最大連續(xù)重連失敗次數(shù)
private int reconnectcount; //socket重連次數(shù)
private boolean reconnectflag;//socket重連標志
private String buffdata =""; //用于斷線緩存
public final static String IRECONNECT = "998"; //與服務器重新連接成功
public final static String ITORECONNECT = "997";//與服務器斷開,正重新連接
public final static String IDISCONNECT = "996";//無法連接服務器
private static int gap;
private static int datagap;
//監(jiān)測運行時,以便及時運行垃圾回收
private Runtime rt = null;
private boolean gcflag = false; //是否要肩負起垃圾收集工作
private Timer timer;
private ConnectKeepTimer connecttimer;
//互斥鎖
private byte[] sendlock = new byte[0]; //發(fā)送函數(shù)互斥
private byte[] disconnectlock = new byte[0];
private byte[] connectlock = new byte[0];
private byte[] dispendatalock = new byte[0];
private byte[] interfacelock = new byte[0];
public SocketManager(boolean gcflag) {
super();
this.gcflag = gcflag;
}
public void init(SocketInterface socketinterface,String ipstring){
this.socketinterface = socketinterface;
this.ipstring = ipstring;
connectflag = false;
Ifthreadstart = false;
reconnectflag = false;
toconnectflag = false;
havesenddata = false;
switchstate = false;
datasendflag = false;
currcount=0;
timer = new Timer();
connecttimer = new ConnectKeepTimer(this);
rt = Runtime.getRuntime();
this.start();
}
public void resetipstring(String ipstring){ //重新設置連接的ip參數(shù)
if(this.ipstring.equals(ipstring))
return;
switchstate = true;
this.ipstring = ipstring;
havesenddata = false;
datasendflag = false;
sendpacket(UniversalDefine.CHECKDATABAG,true);
toconnectflag = false;
connectflag = false;
buffdata = "";
}
public void resetSocInterface(SocketInterface socketinterface){ //重新設置調用這個socket的父級句柄
synchronized(interfacelock){
this.socketinterface = socketinterface;
switchstate = false;
}
}
public static synchronized SocketManager getInstance(){
if(instance == null){
instance = new SocketManager(true);
}
return instance;
}
public void run(){
while(!toconnectflag)
{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (connect()) {
recent = System.currentTimeMillis();
gcrecent = recent;
now = recent;
gap = 0;
Thread t = new Thread(connecttimer);
t.start();
Datagram dg=null;
while (runflag) {
if(!switchstate){ //處在同一服務器
if (havesenddata){ //連接發(fā)送的第一個數(shù)據(jù)包
sendpacket(senddata,true);
havesenddata = false;
}
if (connectflag) {
recpacket ="";
try {
dg = dc.newDatagram(2048);
dc.receive(dg);
recpacket = new String(dg.getData(),0,dg.getLength(),"UTF-8");
}catch(EOFException eofe){
System.out.println(recpacket);
eofe.printStackTrace();
}catch (IOException oe) {
dg.reset();
dg = null;
oe.printStackTrace();
} catch(Exception e){
dg.reset();
dg = null;
e.printStackTrace();
}
if(dg!=null){
gap =0;
dg.reset();
dg = null;
}
if(!recpacket.equals("")){
recent = System.currentTimeMillis();
datatofather();
}
}else{
while(!toconnectflag)
{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(!connect()) {
recpacket = "000|"+IDISCONNECT; //產生無法連接服務器事件
datatofather();
break;
}else{
gap =0;
havesenddata = true;
}
}
}else{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}else{
recpacket = "000|"+IDISCONNECT; //無法連接服務器
datatofather();
}
}
//斷開連接
private synchronized void disconnect(){
synchronized(disconnectlock){
try {
if(dc != null){
dc.close();
}
} catch (IOException e) {
// TODO 自動生成 catch 塊
e.printStackTrace();
}
dc = null;
connectflag = false;
}
}
private void setsendpacket(String packetdata){
havesenddata = true;
toconnectflag = true;
senddata = null;
senddata = packetdata;
}
// 向服務器發(fā)送數(shù)據(jù)
public synchronized void sendpacket(String packetdata,boolean ifbuff) {
synchronized(sendlock){
System.out.println(packetdata);
if(ifbuff){ //是否將數(shù)據(jù)緩存
buffdata = null;
buffdata = packetdata;
if(!toconnectflag){
setsendpacket(packetdata);
}else{
datasendflag = true;
datagap=0;
}
}
if (connectflag){
try {
byte[] bytes = packetdata.getBytes("UTF-8");
// byte[] bytes = packetdata.getBytes();
dc.send(dc.newDatagram(bytes, bytes.length));
} catch (Exception oe) {
disconnect();
System.out.println("socket 連接已斷開");
return;
}
}
packetdata = null;
}
}
//udp連接維護,每1秒種調用一次
public void ConnectKeep(){
if(gap >=2*60){ //超過2分鐘沒接收到消息
disconnect(); //斷開連接
recpacket = "000|"+ITORECONNECT; //產生與服務器斷開連接事件
datatofather();
if(connect()){
recpacket = "000|"+IRECONNECT; //產生服務器重連成功事件
sendpacket(buffdata,true);
datatofather();
}else{
recpacket = "000|"+IDISCONNECT; //產生無法連接服務器事件
datatofather();
}
gap = 0;
}
System.out.println("freeMory2: "+String.valueOf(rt.freeMemory()));
System.out.println("totalMory2: "+String.valueOf(rt.totalMemory()));
if(gcflag){ //判斷是否有垃圾回收任務,且上次調用會收后超過3秒
//在性能過耗(可用內存不到當前內存總量的2/5時),進行垃圾回收GC
System.out.println("freeMory: "+String.valueOf(rt.freeMemory()));
System.out.println("totalMory: "+String.valueOf(rt.totalMemory()));
if(rt.freeMemory() < (rt.totalMemory() * 2/5)){
rt.gc();
}
}
now = System.currentTimeMillis();
if(datagap>5){//超過5秒沒接收到業(yè)務響應數(shù)據(jù)
if(!buffdata.equals("")&&datasendflag)
this.sendpacket(buffdata,true);
datagap = 0;
}
if(currcount>=30){ ///每30秒發(fā)一次檢測包
sendpacket(UniversalDefine.CHECKDATABAG,false);
currcount = 0;
}
gap++;
datagap++;
currcount++;
}
// 連接服務器
private synchronized boolean connect() {
synchronized(connectlock){
if(!connectflag){
try {
disconnect();
dc = (DatagramConnection) Connector.open(ipstring);
connectflag = true;
if(!reconnectflag){
System.out.println("socket connect successful");
reconnectflag = true;
}else{
System.out.println("socket reconnect successful");
}
} catch (ConnectionNotFoundException cnfe) {
reconnectcount++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自動生成 catch 塊
e.printStackTrace();
}
if(reconnectcount>=MAXCOUNT){
return false;
}else{
return connect();
}
} catch (IOException ioe) {
if (!connectflag) {
ioe.printStackTrace();
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
return true;
}
}
// 把接收到的數(shù)據(jù)做初步解析后,山選出業(yè)務數(shù)據(jù)分發(fā)給相應的處理模塊
private synchronized void datatofather() {
synchronized(dispendatalock){
System.out.println("Received . :" + recpacket);
int ifcheck=999; //檢測包標志999 為檢測包 997/998 表示socket連接已經斷開/連接上 其他 為業(yè)務數(shù)據(jù)包
String errcode = "";
StringTokenizer stringtokenizer = new StringTokenizer(recpacket, UniversalDefine.DIVISION);
if(stringtokenizer.hasMoreTokens()){
errcode = stringtokenizer.nextToken();
if(errcode.equals("000")){
if (stringtokenizer.hasMoreTokens()) {
ifcheck = Integer.parseInt(stringtokenizer.nextToken());
}
if(ifcheck != 999 && !recpacket.equals("")){//不是檢測包
datasendflag = false;
synchronized(interfacelock){
socketinterface.RecvieData(recpacket);
}
}
}else if(errcode.equals("001")){ //業(yè)務數(shù)據(jù)發(fā)送成功響應包
datasendflag = false;
datagap=0;
}
}
stringtokenizer.setNull();
stringtokenizer = null;
errcode = null;
}
}
// 啟動socketmanager實例線程,并保證socket連接已經建立
public void socketthreadstart() {
if (!Ifthreadstart){
Ifthreadstart = true;
this.start();
while(!connectflag){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void setNull(){
runflag = false;
socketinterface = null;
if(timer!=null)
timer.cancel();
try {
dc.close();
} catch (IOException e) {
e.printStackTrace();
}
instance = null;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -