android socket 长连接

tcp长连接+后台service+异步socket实例

总结一下后台服务编程,以及socket实现是一些注意事项。

1,service的生命周期:

//startService() 启动Service
其生命周期为context.startService() ->onCreate()- >onStart()->Service running-->context.stopService() | ->onDestroy() ->Service stop 
//对于bindService()启动Service:
context.bindService()->onCreate()->onBind()->Service running-->onUnbind() -> onDestroy() ->Service stop

2,怎么拿到service实例

3,startService()及bindService()使用

4,socket的accept,read,write阻塞解决

好吧,直接上代码

GamepadSocketServer.java

package com.example.gamepaddemo.gamepadserver;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URLDecoder;

import org.json.JSONException;
import org.json.JSONObject;


import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;

/**
 * @author zhouxueliang
 * 1、接收连接请求,控制手柄界面
 * 2、发送数据
 */
public class GamepadSocketServer extends Service {
    public static final int GAMEPAD_REQUEST_START_ACTIVITY = 0;
    public static final int GAMEPAD_REQUEST_STOP_ACTIVITY  = GAMEPAD_REQUEST_START_ACTIVITY +1;
    
    
    /**
     * 监听端口
     */
    private static final int PORT = 24000; 
    
    /**
     * SocketServer开关标志
     */
    public boolean isSocketServerStarted = false;
    
    
    /**
     * 客户端Socket
     */
    private Socket clientSocket = null;
    private DataInputStream cInputStream = null;
    private DataOutputStream cOutputStream = null;
    
    /**
     * Server Socket
     */
    private ServerSocket serverSocket = null;
    
    /**
     * 线程切换使用handler
     */
    private Handler workHandler = new Handler();
    
    /**
     * 界面回调handler
     */
    private Handler helperListener = null;
    
    /**
     * 服务启动是启动socket监听
     */
    @Override
    public void onCreate() {    
        startSocketServer();
        super.onCreate();
    }
    
 
    /**
     * 服务销毁是是停止socket监听
     */
    @Override
    public void onDestroy() {
        stopSocketServer();
        helperListener = null;
        super.onDestroy();
    }
    
    /**
     * 启动socket监听
     */
    public void startSocketServer() {
        if (!isSocketServerStarted) {
            try {
                /**
                 * 启动ServerSocket
                 */
                serverSocket = new ServerSocket(PORT);
                isSocketServerStarted = true;            
            } catch (IOException e) {
                e.printStackTrace();
            }
            
            
            /**
             * Accept Socket
             */
            new Thread(new AcceptRunnable()).start();
        }
    }
    
    
    /**
     * 停止socket监听
     */
    public void stopSocketServer() {
        if (isSocketServerStarted && serverSocket != null) {
            try {
                isSocketServerStarted = false;    
                if (clientSocket !=null && !clientSocket.isClosed()) {
                    clientSocket.close();
                    clientSocket = null;
                }
                serverSocket.close();
                serverSocket = null;
            } catch (IOException e) {
                e.printStackTrace();
            }            
        }
    }    

    /**
     * 设置界面回调监听者
     */
    public void setHelperListener(Handler listener) {
        helperListener = listener;
    }
    
    
    /**
     * Socket Accept 线程(非阻塞)
     */
    public class AcceptRunnable implements Runnable {
        @Override
        public void run() {
            while (isSocketServerStarted) {
                try {
                    /**
                     * 监听连接, 阻塞
                     */
                    final Socket client  = serverSocket.accept();
                    
                    /**
                     * 回调主线程
                     */
                    workHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            onGetClient(client);
                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }    
            }
        }
    }
    
    
    /**
     * Socket read 线程(非阻塞)
     */
    public class RecieverRunnable implements Runnable {
        private boolean runnable = true;
        @Override
        public void run() {
            while (runnable) {
                String inputString = null;
                int len = 0;
                try {
                    /**
                     * 等待read数据包大小,阻塞
                     */
                    len = cInputStream.readInt();
                    
                    /**
                     * read到数据包大小,read数据,阻塞
                     */
                    if (len > 0) {
                        byte[] input = new byte[len];
                        int l = -1;
                        int readlen = 0;
                        while(len-readlen > 0 && (l = cInputStream.read(input, readlen , len-readlen)) != -1){
                            readlen += l;
                        }
                        inputString = URLDecoder.decode(new String(input), "UTF-8");
                    }
                    
                } catch (IOException e) {
                    runnable = false;
                    e.printStackTrace();
                }
                
                /**
                 * 解析请求
                 */
                final RequestInfo requestInfo = parseInputString(inputString);
                if (requestInfo != null) {
                    /**
                     * read请求,回调主线程
                     */
                    workHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            onGetRequest(requestInfo);
                        }
                    });
                }
            }
        }
    }
    
    
    /**
     * accept请求,回调主线程
     */
    private void onGetClient(Socket client) {    
        if(initClientSocket(client)==0) {
            ;
        }        
    }
    
    
    /**
     * read(request)请求,回调主线程
     */
    private void onGetRequest(RequestInfo info) {    
        if(info != null) {
            if (info.target.equals("GamepadRequest")) {
                if (info.type == 0) {
                    stopGamepadActivity(info);
                }
                else {
                    startGamepadActivity(info);
                }
            }
        }        
    }
    
    
    /**
     * 请求拉起界面
     */
    private void startGamepadActivity(RequestInfo info) {
        if (helperListener !=null) {
            Message message = helperListener.obtainMessage(GAMEPAD_REQUEST_START_ACTIVITY, info);
            helperListener.sendMessage(message);
        }
    }
    
    
    /**
     * 请求关闭界面
     */
    private void stopGamepadActivity(RequestInfo info) {
        if (helperListener !=null) {
            Message message = helperListener.obtainMessage(GAMEPAD_REQUEST_STOP_ACTIVITY, info);
            helperListener.sendMessage(message);
        }
    }
    
    
    /**
     * 往客户端发送数据
     */
    public void respondMessage(JSONObject obj) {
        try {
            if (cOutputStream != null) {
                String utf8String = new String(obj.toString().getBytes(), "UTF-8");
                cOutputStream.writeInt(utf8String.getBytes().length);
                cOutputStream.write(utf8String.getBytes());
                cOutputStream.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    
    /**
     * 初始化客户端数据
     */
    private int initClientSocket(Socket cSocket) {
        try {
            
            /**
             * 重置
             */
            if  (cInputStream != null) {
                cInputStream.close();
                cInputStream = null;
            }            
            if  (cOutputStream != null) {
                cOutputStream.close();
                cOutputStream = null;
            }
            if  (clientSocket != null) {
                clientSocket.close();
                clientSocket = null;
            }
            
            /**
             * 重设
             */
            clientSocket = cSocket;
            cInputStream = new DataInputStream(clientSocket.getInputStream());
            cOutputStream = new DataOutputStream(clientSocket.getOutputStream());
            new Thread(new RecieverRunnable()).start();
        } catch (IOException e) {
            e.printStackTrace();
            return -1;
        }
        return 0;
    }
    
    /**
     * 服务的Binder
     */
    public GamepadServerBinder mBinder = new GamepadServerBinder();    
    public class GamepadServerBinder extends Binder {        
        public GamepadSocketServer getService() {
            /**
             * 返回service实例
             */
            return GamepadSocketServer.this;
        }
    }
    
    /**
     * 绑定服务
     */
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
    
    /**
     * 重新绑定服务
     */
    @Override
    public void onRebind(Intent intent) {
        super.onRebind(intent);
    }
    
    
    /**
     * 解析数据
     */
    private RequestInfo parseInputString(String inputString) {
        if (inputString != null && inputString.length() > 0) {
            JSONObject object = null;
            RequestInfo request = null;
            try {
                object = new JSONObject(inputString);
                if (object != null) {
                    request = new RequestInfo();
                    request.target = object.getString("target");
                    request.type = object.getInt("type");
                    request.peerId = object.getString("peerId");
                    request.pcClientVersion = object.getString("pcClientVersion");
                }
                return request;
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    
    /**
     * 请求数据结构
     */
    public static class RequestInfo {
        String target;
        int    type;
        String peerId;
        String pcClientVersion;
    }
}

GamepadServerHelper.java

package com.example.gamepaddemo.gamepadserver;


import java.lang.ref.WeakReference;

import org.json.JSONException;
import org.json.JSONObject;
import com.example.gamepaddemo.gamepadview.GamepadActivity;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;


/**
 * 负责界面与socket服务的交互
 * @author zhouxueliang
 */
public class GamepadServerHelper {
    private boolean isServiceStarted = false;
    
    /**
     * service
     */
    private GamepadSocketServer gamepadServer = null;

    private Context mContext = null;

    /** 单例  **/
    private static GamepadServerHelper instance;
    public synchronized static GamepadServerHelper getInstance(Context context)
    {
        if (instance == null) {
            instance = new GamepadServerHelper(context);
        }
        return instance;
    }
    
    private GamepadServerHelper(Context context) {
        mContext = context;
    }
    
    
    /** 
     * 监听service回调 
     */
    private MessageListener gamepadServerMessageListener = new MessageListener() {        
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case GamepadSocketServer.GAMEPAD_REQUEST_START_ACTIVITY:
            {
                RequestInfo  info = (RequestInfo)msg.obj;
                Intent intent = new Intent(new Intent(mContext, GamepadActivity.class));
                intent.putExtra("type", info.type);
                mContext.startActivity(intent);
            }
                break;
            case GamepadSocketServer.GAMEPAD_REQUEST_STOP_ACTIVITY:
            {
                Intent intent = new Intent(new Intent(mContext, GamepadActivity.class));
                intent.putExtra("type", 0);
                mContext.startActivity(intent);
            }
                break;

            default:
                break;
            }
        }
    };
    private Handler helperHander = new StaticHandler(gamepadServerMessageListener);
    
    
    
    /** 
     * ServiceConnection,获取service实例
     */
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            gamepadServer = null;
        }
        
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            gamepadServer = ((GamepadSocketServer.GamepadServerBinder)service).getService();
            gamepadServer.setHelperListener(helperHander);
        }
    };
    
    /**
     *  启动手柄服务
     */
    public synchronized void startService(){    
        if(!isServiceStarted) {
            isServiceStarted = true;
            
            Intent intent = new Intent();
            intent.setClass(mContext, GamepadSocketServer.class);
            
            mContext.startService(intent);
            mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        }
    }
    
    /**
     *  关闭手柄服务
     */
    public synchronized void stopService(){
        if(isServiceStarted) {
            isServiceStarted = false;
            
            Intent intent = new Intent();
            intent.setClass(mContext, GamepadSocketServer.class);
            
            mContext.unbindService(mConnection);
            mContext.stopService(intent);
            gamepadServer = null;
        }
    }
    
    /**
     *  发送消息
     */
    public void sendMessage(JSONObject obj) {
        gamepadServer.respondMessage(obj);
    }
    
    /**
     * 用来消除Handle可能导致的泄漏
     * 原在Util里,鉴于项目独立性,直接移植
     */
    public static class StaticHandler extends Handler {
        WeakReference<MessageListener> listener;
        
        /**
         * 
         * @param listener
         *            必读: 此listener必须由Activity实现该接口(推荐)或者是宿主Activity的类成员 : 这里是弱引用,
         *            不会增加变量的引用计数, 使用匿名变量会导致listener过早释放(请参考此类的引用示例)
         */
        public StaticHandler(MessageListener listener) {
            this.listener = new WeakReference<MessageListener>(listener);
        }
        
        public StaticHandler(Looper looper, MessageListener listener) {
            super(looper);
            this.listener = new WeakReference<MessageListener>(listener);
        }
        
        @Override
        public void handleMessage(Message msg) {
            MessageListener listener = this.listener.get();
            if (listener != null) {
                listener.handleMessage(msg);
            }
        }
    }
    
    /**
     * 原在Util里,鉴于项目独立性,直接移植
     */
    public interface MessageListener {
        public void handleMessage(Message msg);
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值