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实例(binder接口)

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;
    private static Object instanceLock = new Object();

public static GamepadServerHelper getInstance(Context context) { if (instance == null) { synchronized(instanceLock){
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); } }

 

posted on 2013-06-05 18:27  asi24  阅读(12069)  评论(1编辑  收藏  举报