📄 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连接的维护实现
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; //连接维护调用次数
private boolean runflag = true;
private String senddata;
private final static int MAXCOUNT = 3;//socket最大连续重连失败次数
private int reconnectcount; //socket重连次数
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;
//监测运行时,以便及时运行垃圾回收
private Runtime rt = null;
private boolean gcflag = false; //是否要肩负起垃圾收集工作
private Timer timer;
private ConnectKeepTimer connecttimer;
//互斥锁
private byte[] sendlock = new byte[0]; //发送函数互斥
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参数
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){ //连接发送的第一个数据包
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;
}
// 向服务器发送数据
public synchronized void sendpacket(String packetdata,boolean ifbuff) {
synchronized(sendlock){
System.out.println(packetdata);
if(ifbuff){ //是否将数据缓存
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秒没接收到业务响应数据
if(!buffdata.equals("")&&datasendflag)
this.sendpacket(buffdata,true);
datagap = 0;
}
if(currcount>=30){ ///每30秒发一次检测包
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;
}
}
// 把接收到的数据做初步解析后,山选出业务数据分发给相应的处理模块
private synchronized void datatofather() {
synchronized(dispendatalock){
System.out.println("Received . :" + recpacket);
int ifcheck=999; //检测包标志999 为检测包 997/998 表示socket连接已经断开/连接上 其他 为业务数据包
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")){ //业务数据发送成功响应包
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 + -