你画我猜核心功能实现 Android客户端+Java服务端

     本篇文章是我以前写的一篇文章的改版,上一篇文章已删除,因为以前的博客有的朋友说运行不起来,我现在想起来所以重新修改了以下代码,因为我这测试机就两个,只能测试一个绘制者和一个观看者。

下面上代码,首先是我们的Android客户端-------------------

Android实现原理就是自定义View,然后继承的是SurfaceView,不继承View的原因就是SurfaceView这个视图里内嵌了一个专门用于绘制的Surface。

先看一下我们自定义的DrawGameView,也就是继承自SurfaceView的一个View。

 

public class DrawGameView extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder holder;
    private SurfaceThread thread;
    WindowManager wm = (WindowManager) getContext()
            .getSystemService(Context.WINDOW_SERVICE);

    int screenW = wm.getDefaultDisplay().getWidth();
    int screenH = wm.getDefaultDisplay().getHeight();
//    private Canvas canvas;

    public SurfaceThread getThread() {
        return thread;
    }

    public DrawGameView(Context context) {
        super(context);
        init();
    }

    public DrawGameView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public void init() {
        holder = getHolder();
        holder.addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        thread = new SurfaceThread();
        thread.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    public class SurfaceThread extends Thread {
        private Path path;
        private Paint paint;
        private ArrayList<DrawStep> steps = new ArrayList<DrawStep>();
        private ArrayList<Path> paths = new ArrayList<Path>();

        public SurfaceThread() {
            path = new Path();
            paint = new Paint();
            paint.setAntiAlias(true);
            paint.setColor(Color.BLUE);
            paint.setStrokeWidth(5);
            paint.setStyle(Paint.Style.STROKE);
        }

        @Override
        public void run() {
            super.run();
            while (true) {
                draw();
                try {
                    Thread.sleep(17);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        public void addStep(DrawStep step) {
            steps.add(step);
        }

        public void draw() {
            Canvas canvas = null;
            try {
                canvas = holder.lockCanvas();//锁整个画布
                if (canvas != null) {
                    while (steps.size() > 0) {
                        DrawStep step = steps.remove(0);
                        if (step.getType() == DrawStep.MoveTo) {
                            path.moveTo(screenW * ((float) step.getxP() / 10000), screenH * ((float) step.getyP() / 10000));
                        } else if (step.getType() == DrawStep.LineTo) {
                            path.lineTo(screenW * ((float) step.getxP() / 10000), screenH * ((float) step.getyP() / 10000));
                        } else if (step.getType() == DrawStep.UP) {
                            Path path1 = new Path(path);
                            paths.add(path1);
                        }
                    }

                    for (int i = 0; i < paths.size(); i++) {
                        canvas.drawPath(paths.get(i), paint);
                    }
                    canvas.drawPath(path, paint);
                    holder.unlockCanvasAndPost(canvas);
                }
            } catch (Exception e) {
            }
        }
    }
}

 

我先把所有代码贴上吧,没什么东西,如果有问题可以给我发私信。

 

MainActivity代码

 

public class MainActivity extends Activity {
    private static DrawGameView drawGameView;

    DisplayMetrics dm = new DisplayMetrics();

    int screenW;
    int screenH;

    @SuppressLint("ClickableViewAccessibility")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        NetWorkMessage.get_Instance().setActivity(this);

        drawGameView = new DrawGameView(this);
        setContentView(drawGameView);

        getWindowManager().getDefaultDisplay().getMetrics(dm);
        screenW = dm.widthPixels;
        screenH = dm.heightPixels;

        drawGameView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (NetWorkMessage.get_Instance().isDrawer()) {
//                if (true) {
                    switch (event.getAction() & MotionEvent.ACTION_MASK) {
                        case MotionEvent.ACTION_DOWN:
                            addStep(DrawStep.MoveTo, (int) (event.getX() / screenW * 10000), (int) (event.getY() / screenH * 10000));
                            break;
                        case MotionEvent.ACTION_MOVE:
                            addStep(DrawStep.LineTo, (int) (event.getX() / screenW * 10000), (int) (event.getY() / screenH * 10000));
                            break;
                        case MotionEvent.ACTION_UP:
                            addStep(DrawStep.UP, 0, 0);
                            break;
                    }
                    return true;
                } else {
                    return false;
                }
            }
        });


    }

    public void addStep(byte type, int xp, int yp) {
        DrawStep step = new DrawStep();
        step.setType(type);
        step.setxP(xp);
        step.setyP(yp);

        NetWorkMessage.get_Instance().sendDrawMsgToServer(step);
        addOneStep(step);
    }

    public void addOneStep(DrawStep step) {
        drawGameView.getThread().addStep(step);
    }


//    public static void drawStep(DrawStep drawStep) {
//        drawGameView.postInvalidate();
        drawView.forceLayout();
//    }
}

 

 

 

GameApplication在这里做了Socket的初始化

 

public class GameApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        NetWorkMessage.get_Instance().createNetWork();
//        NetWorkMessage.get_instaance().receiveLoginNetWork();
        NetWorkMessage.get_Instance().receiveDrawNetWork();
    }
}

Command定义的服务器与客户端交互的命令

 

public class Command {
    public static final byte LOGIN = 1;
    public static final byte DRAW = 2;

    public static final byte LOGIN_OUT = 3;//登出
}

NetWorkMessage主要是处理Socket连接、接收和发送数据的

 

public class NetWorkMessage {
    private final String TAG = "NetWorkMessage";

    private Socket socket = new Socket();
    private static NetWorkMessage _instance = new NetWorkMessage();
    public boolean isDraw;
    private MainActivity activity;

    public MainActivity getActivity() {
        return activity;
    }

    public void setActivity(MainActivity activity) {
        this.activity = activity;
    }

    public static NetWorkMessage get_Instance() {
        return _instance;
    }


    public void sendDrawMsgToServer(DrawStep drawStep) {
        try {
            //发送内容
            DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
            int len = 10;
            ByteArray data = new ByteArray();
            data.writeInt(len);
            data.writeByte(Command.DRAW);
            data.writeByte(drawStep.getType());
            data.writeInt(drawStep.getxP());
            data.writeInt(drawStep.getyP());
            outputStream.write(data.toByteArray());
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
            Log.d(TAG, "没有发送成功======客户端----断开连接");
        }
    }

    public void createNetWork() {
        new Thread(createNetwork).start();
    }

    public void receiveDrawNetWork() {
        new Thread(receiveDrawNetwork).start();
    }

    private Runnable createNetwork = new Runnable() {
        @Override
        public void run() {
            try {
//                socket = new Socket("192.168.0.102", 8888);
                socket = new Socket("192.168.1.105", 8888);

                requestLogin();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    };

    /**
     * 请求登录
     */
    private void requestLogin()
    {
        try{
            DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
            String userKey = (String) SharedPreferencesUtil.getData(getActivity(), Configs.LOCAL_USER_KEY, "");
            int len = 5 + userKey.length();
            ByteArray data = new ByteArray();
            data.writeInt(len);
            data.writeByte(Command.LOGIN);
            data.writeByteArray(userKey.getBytes());
            outputStream.write(data.toByteArray());
            outputStream.flush();
        }catch (Exception e)
        {

        }
    }


    private Runnable receiveDrawNetwork = new Runnable() {
        @Override
        public void run() {
            while (true) {
                receiveDraw();
            }
        }
    };

    private void receiveDraw() {
        //接收服务器返回信息
        try {
            DataInputStream inputStream = new DataInputStream(socket.getInputStream());
            if (inputStream.available() != 0) {
                int len = inputStream.readInt();
                byte[] buffer = new byte[len];
                inputStream.read(buffer, 0, len);
                ByteArray data = new ByteArray(buffer);
                byte cmd = data.readByte();
                if (cmd == Command.LOGIN) {
                    Log.d(TAG, "-----------BEGIN-----------------");
                    byte[] userKeyByteArr = data.readByteArray(5, 36);
                    Log.d(TAG, "-----------EDN-----------------");
                    String userKey = new String(userKeyByteArr);
                    if (userKey != null && !"".equals(userKey))
                    {
                        SharedPreferencesUtil.saveData(getActivity(), Configs.LOCAL_USER_KEY, userKey);
                    }
                    Log.d(TAG, "userKey=============" + userKey);
                    //12e0962f-3789-48a5-9b9e-74a256544949
                    int tag = data.readInt();
                    Log.d(TAG, "tag=============" + tag);
                    if (tag == 1) {
                        setDrawer(true);
                    } else {
                        setDrawer(false);
                    }
                } else if (cmd == Command.DRAW) {
                    byte type = data.readByte();
                    int x = data.readInt();
                    int y = data.readInt();

                    DrawStep drawStep = new DrawStep();
                    drawStep.setxP(x);
                    drawStep.setyP(y);
                    drawStep.setType(type);

                    activity.addOneStep(drawStep);
                }
//                MainActivity.drawStep(msg);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public boolean isDrawer() {
        return isDraw;
    }

    public void setDrawer(boolean draw) {
        isDraw = draw;
    }


}

DrawSept,绘制的时候前后台交互传输的数据格式

 

public class DrawStep {
    public static final byte MoveTo = 1;
    public static final byte LineTo = 2;
    public static final byte UP = 3;

    private byte type;
    private int xP;

    private int yP;


    public byte getType() {
        return type;
    }

    public void setType(byte type) {
        this.type = type;
    }

    public int getxP() {
        return xP;
    }

    public void setxP(int xP) {
        this.xP = xP;
    }

    public int getyP() {
        return yP;
    }

    public void setyP(int yP) {
        this.yP = yP;
    }
}

SharePreferencesUtil 本地存储工具类,用来存储服务器返回的userKey

 

public class SharedPreferencesUtil {
    //存储的sharedpreferences文件名
    private static final String FILE_NAME = "save_file_name";

    /**
     * 保存数据到文件
     *
     * @param context
     * @param key
     * @param data
     */
    public static void saveData(Context context, String key, Object data){

        String type = data.getClass().getSimpleName();
        SharedPreferences sharedPreferences = context
                .getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();

        if ("Integer".equals(type)){
            editor.putInt(key, (Integer)data);
        }else if ("Boolean".equals(type)){
            editor.putBoolean(key, (Boolean)data);
        }else if ("String".equals(type)){
            editor.putString(key, (String)data);
        }else if ("Float".equals(type)){
            editor.putFloat(key, (Float)data);
        }else if ("Long".equals(type)){
            editor.putLong(key, (Long)data);
        }

        editor.commit();
    }

    /**
     * 清除本地保存的数据
     *
     * @param context
     * @param key
     */
    public static void removeData(Context context, String key)
    {
        SharedPreferences sharedPreferences = context
                .getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.remove(key);
        editor.commit();
    }

    /**
     * 从文件中读取数据
     * @param context
     * @param key
     * @param defValue
     * @return
     */
    public static Object getData(Context context, String key, Object defValue){

        String type = defValue.getClass().getSimpleName();
        SharedPreferences sharedPreferences = context.getSharedPreferences (FILE_NAME, Context.MODE_PRIVATE);

        //defValue为为默认值,如果当前获取不到数据就返回它
        if ("Integer".equals(type)){
            return sharedPreferences.getInt(key, (Integer)defValue);
        }else if ("Boolean".equals(type)){
            return sharedPreferences.getBoolean(key, (Boolean)defValue);
        }else if ("String".equals(type)){
            return sharedPreferences.getString(key, (String)defValue);
        }else if ("Float".equals(type)){
            return sharedPreferences.getFloat(key, (Float)defValue);
        }else if ("Long".equals(type)){
            return sharedPreferences.getLong(key, (Long)defValue);
        }

        return null;
    }
}

ByteArray

 

public class ByteArray {
    /**
     * DEFAULT_SIZE
     */
    private static final byte DEFAULT_SIZE = 16;
    /**
     * BOOLEAN_SIZE
     */
    static final public byte BOOLEAN_SIZE = 1;
    /**
     * BYTE_SIZE
     */
    static final public byte BYTE_SIZE = 1;
    /**
     * CHAR_SIZE
     */
    static final public byte CHAR_SIZE = 2;
    /**
     * SHORT_SIZE
     */
    static final public byte SHORT_SIZE = 2;
    /**
     * INT_SIZE
     */
    static final public byte INT_SIZE = 4;
    /**
     * LONG_SIZE
     */
    static final public byte LONG_SIZE = 8;
    /**
     * 当前位置
     */
    private int currentPos = 0;
    /**
     * byte数组数据
     */
    private byte[] data;

    /**
     * 默认大小构造
     */
    public ByteArray() {
        this(DEFAULT_SIZE);
    }

    /**
     * 指定大小构造
     *
     * @param size 指定的大小
     */
    public ByteArray(int size) {
        data = new byte[size];
        currentPos = 0;
    }

    /**
     * 指定数据构造
     *
     * @param src 指定的数据源
     */
    public ByteArray(byte[] src) {
        data = src;
        currentPos = 0;
    }

    /**
     * writeBoolean
     *
     * @param val
     */
    public void writeBoolean(boolean val) {
        ensureCapacity(BOOLEAN_SIZE);
        data[currentPos++] = (byte) (val ? 1 : 0);
    }

    /**
     * writeByte
     *
     * @param val
     */
    public void writeByte(byte val) {
        ensureCapacity(BYTE_SIZE);
        data[currentPos++] = val;
    }

    /**
     * writeByte
     *
     * @param val
     */
    public void writeByte(int val) {
        writeByte((byte) val);
    }

    /**
     * writeChar
     *
     * @param c
     */
    public void writeChar(char c) {
        ensureCapacity(CHAR_SIZE);
        data[currentPos + 1] = (byte) (c >>> 0);
        data[currentPos + 0] = (byte) (c >>> 8);
        currentPos += 2;
    }

    /**
     * writeShort
     *
     * @param val
     */
    public void writeShort(short val) {
        ensureCapacity(SHORT_SIZE);
        data[currentPos + 1] = (byte) (val >>> 0);
        data[currentPos + 0] = (byte) (val >>> 8);
        currentPos += 2;
    }

    /**
     * writeShort
     *
     * @param val
     */
    public void writeShort(int val) {
        writeShort((short) val);
    }

    /**
     * writeInt
     *
     * @param val
     */
    public void writeInt(int val) {
        ensureCapacity(INT_SIZE);
        data[currentPos + 3] = (byte) (val >>> 0);
        data[currentPos + 2] = (byte) (val >>> 8);
        data[currentPos + 1] = (byte) (val >>> 16);
        data[currentPos + 0] = (byte) (val >>> 24);
        currentPos += INT_SIZE;
    }

    /**
     * writeLong
     *
     * @param val
     */
    public void writeLong(long val) {
        ensureCapacity(LONG_SIZE);
        data[currentPos + 7] = (byte) (val >>> 0);
        data[currentPos + 6] = (byte) (val >>> 8);
        data[currentPos + 5] = (byte) (val >>> 16);
        data[currentPos + 4] = (byte) (val >>> 24);
        data[currentPos + 3] = (byte) (val >>> 32);
        data[currentPos + 2] = (byte) (val >>> 40);
        data[currentPos + 1] = (byte) (val >>> 48);
        data[currentPos + 0] = (byte) (val >>> 56);
        currentPos += LONG_SIZE;
    }

    /**
     * writeByteArray
     *
     * @param src
     */
    public void writeByteArray(byte[] src) {
        if (src == null) {
            return;
        }
        ensureCapacity(src.length);
        System.arraycopy(src, 0, data, currentPos, src.length);
        currentPos += src.length;
    }

    /**
     * writeUTF
     *
     * @param str
     */
    public void writeUTF(String str) {
        writeByteArray(getByteArrFromUTF(str));
    }

    /**
     * readBoolean
     *
     * @return
     */
    public boolean readBoolean() {
//        if(checkCapacity(BOOLEAN_SIZE)){
//            return false;
//        }
        return data[currentPos++] != 0;
    }

    /**
     * readByte
     *
     * @return
     */
    public byte readByte() {
//        if(checkCapacity(BYTE_SIZE)){
//            return -1;
//        }
        return data[currentPos++];
    }

    /**
     * readChar
     *
     * @return
     */
    public char readChar() {
//        if(checkCapacity(CHAR_SIZE)){
//            return '1';
//        }
        char c = (char) (((data[currentPos + 1] & 0xFF) << 0) +
                ((data[currentPos + 0] & 0xFF) << 8));
        currentPos += CHAR_SIZE;
        return c;
    }

    /**
     * readShort
     *
     * @return
     */
    public short readShort() {
        short s = (short) (((data[currentPos + 1] & 0xFF) << 0) +
                ((data[currentPos + 0] & 0xFF) << 8));
        currentPos += SHORT_SIZE;
        return s;
    }

    /**
     * readInt
     *
     * @return
     */
    public int readInt() {
        int i = ((data[currentPos + 3] & 0xFF) << 0) +
                ((data[currentPos + 2] & 0xFF) << 8) +
                ((data[currentPos + 1] & 0xFF) << 16) +
                ((data[currentPos + 0] & 0xFF) << 24);
        currentPos += INT_SIZE;
        return i;
    }

    /**
     * readLong
     *
     * @return
     */
    public long readLong() {
        long l = ((data[currentPos + 7] & 0xFFL) << 0) +
                ((data[currentPos + 6] & 0xFFL) << 8) +
                ((data[currentPos + 5] & 0xFFL) << 16) +
                ((data[currentPos + 4] & 0xFFL) << 24) +
                ((data[currentPos + 3] & 0xFFL) << 32) +
                ((data[currentPos + 2] & 0xFFL) << 40) +
                ((data[currentPos + 1] & 0xFFL) << 48) +
                ((data[currentPos + 0] & 0xFFL) << 56);
        currentPos += LONG_SIZE;
        return l;
    }

    /**
     * readByteArray
     *
     * @param length
     * @return
     */
    public byte[] readByteArray(int length) {
        if (length == -1 || currentPos + length > data.length) {
            length = data.length - currentPos;
        }
        byte[] temp = new byte[length];
        System.arraycopy(data, currentPos, temp, 0, length);
        currentPos += length;
        return temp;
    }

    /**
     * readByteArray
     *
     * @param off
     * @param length
     * @return
     */
    public byte[] readByteArray(int off, int length) {
        if (length == -1 || off + length > data.length) {
            length = data.length - off;
        }
        byte[] temp = new byte[length];
        System.arraycopy(data, off, temp, 0, length);
        return temp;
    }

    /**
     * readUTF
     *
     * @return
     */
    public String readUTF() {
        int utflen = readUnsignedShort();
        if (utflen == -1) {
            System.err.println("Error!! ByteArray: readUTF()");
            return "ERROR";
        }
        byte[] bytearr = null;
        char[] chararr = null;

        bytearr = readByteArray(utflen);
        chararr = new char[utflen];

        int c, char2, char3;
        int count = 0;
        int chararr_count = 0;

        while (count < utflen) {
            c = (int) bytearr[count] & 0xff;
            if (c > 127) {
                break;
            }
            count++;
            chararr[chararr_count++] = (char) c;
        }

        while (count < utflen) {
            c = (int) bytearr[count] & 0xff;
            switch (c >> 4) {
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7: /* 0xxxxxxx*/
                    count++;
                    chararr[chararr_count++] = (char) c;
                    break;
                case 12:
                case 13: /* 110x xxxx   10xx xxxx*/
                    count += 2;
                    char2 = (int) bytearr[count - 1];
                    chararr[chararr_count++] = (char) (((c & 0x1F) << 6) |
                            (char2 & 0x3F));
                    break;
                case 14: /* 1110 xxxx  10xx xxxx  10xx xxxx */
                    count += 3;
                    char2 = (int) bytearr[count - 2];
                    char3 = (int) bytearr[count - 1];
                    chararr[chararr_count++] = (char) (((c & 0x0F) << 12) |
                            ((char2 & 0x3F) << 6) |
                            ((char3 & 0x3F) << 0));
                    break;
                default:
                    break;
            }
        }
        return new String(chararr, 0, chararr_count);
    }

    /**
     * 检测data数组是否足够长
     *
     * @param length int
     */
    private void ensureCapacity(int length) {
        if (currentPos + length >= data.length) {
            byte[] tmp = new byte[data.length + 2 * length];
            System.arraycopy(data, 0, tmp, 0, data.length);
            data = tmp;
        }
    }

    /**
     * getByteArrFromUTF
     *
     * @param str
     * @return
     */
    public static byte[] getByteArrFromUTF(String str) {
        int strlen = str.length();
        int utflen = 0;
        int c, count = 0;

        /* use charAt instead of copying String to char array */
        for (int i = 0; i < strlen; i++) {
            c = str.charAt(i);
            if ((c >= 0x0001) && (c <= 0x007F)) {
                utflen++;
            } else if (c > 0x07FF) {
                utflen += 3;
            } else {
                utflen += 2;
            }
        }

        byte[] bytearr = new byte[utflen + 2];

        bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
        bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);

        int i = 0;
        for (i = 0; i < strlen; i++) {
            c = str.charAt(i);
            if (!((c >= 0x0001) && (c <= 0x007F))) {
                break;
            }
            bytearr[count++] = (byte) c;
        }

        for (; i < strlen; i++) {
            c = str.charAt(i);
            if ((c >= 0x0001) && (c <= 0x007F)) {
                bytearr[count++] = (byte) c;

            } else if (c > 0x07FF) {
                bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
                bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
                bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
            } else {
                bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
                bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
            }
        }
        return bytearr;
    }

    /**
     * readUnsignedByte
     *
     * @return
     */
    private int readUnsignedByte() {
        return data[currentPos++] & 0x00FF;
    }

    /**
     * readUnsignedShort
     *
     * @return
     */
    private int readUnsignedShort() {
        int ch1 = readUnsignedByte();
        int ch2 = readUnsignedByte();
        if ((ch1 | ch2) < 0) {
            return -1;
        }
        return (ch1 << 8) + (ch2 << 0);
    }

    /**
     * toByteArray
     *
     * @return
     */
    public byte[] toByteArray() {
        if (currentPos < data.length) {
            return readByteArray(0, currentPos);
        }
        return data;
    }

    /**
     * resetPosition
     */
    public void resetPosition() {
        currentPos = 0;
    }

    /**
     * close
     */
    public void close() {
        data = null;
    }

    /**
     * bytesToInts
     *
     * @param bytes
     * @return
     */
    public static int[] bytesToInts(byte[] bytes) {
        if (bytes == null || bytes.length < 4) {
            return null;
        }
        int[] ints = new int[bytes.length >> 2];
        ByteArray ba = new ByteArray(bytes);
        for (int i = 0, kk = ints.length; i < kk; i++) {
            ints[i] = ba.readInt();
        }
        return ints;
    }

    /**
     * intsToBytes
     *
     * @param ints
     * @return
     */
    public static byte[] intsToBytes(int[] ints) {
        if (ints == null || ints.length <= 0) {
            return null;
        }
        byte[] bytes = new byte[ints.length << 2];
        ByteArray ba = new ByteArray(bytes);
        for (int i = 0, kk = ints.length; i < kk; i++) {
            ba.writeInt(ints[i]);
        }
        return ba.toByteArray();
    }

    /**
     * getLength
     *
     * @return
     */
    public int getLength() {
        return data.length;
    }

    /**
     * 得到字节数组
     *
     * @return byte[]
     */
    public byte[] toArray() {
        byte[] tmp = new byte[currentPos];
        System.arraycopy(data, 0, tmp, 0, currentPos);
        return tmp;
    }

    /**
     * 追加byte数组
     *
     * @param data
     */
    public void append(byte[] data) {
        writeByteArray(data);
    }
}

然后就是服务器源码---------

DrawServer

 

public class DrawServer
{
    private static DrawServer _instance;

    private static HashMap<Integer,SocketThread> users=new HashMap<Integer, SocketThread>();//用户key,线程
    private int index=0;

    public static void main(String[] args) {

        DrawServer.getInstance().start();

    }
    public static DrawServer getInstance()
    {
        if (_instance == null)
        {
            synchronized (DrawServer.class)
            {
                if (_instance == null)
                {
                    _instance = new DrawServer();
                }
            }
        }
        return _instance;
    }

    private void start() {
        try {
            @SuppressWarnings("resource")
            ServerSocket server = new ServerSocket(8888);// 创建一个Socket服务器对象,进行监听8888的端口
            System.out.println("------服务器启动------");
            while (true) {
                Socket client = server.accept();// 收到一个客户端连接
                System.out.println("------服务器监听到一个客户端连接------");

                addUser(new SocketThread(client)).start();// 开启一个线程与客户端进行数据传输

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public SocketThread addUser(SocketThread thread)
    {
        LoginHandler.getInstance().setOnClientLogin(new LoginHandler.IOnClientLoginListener() {
            @Override
            public void onLogin(String userKey) {
                if (userKey == null || "".equals(userKey))
                {
                    index++;
                    //发送第一次登陆成功消息
                    LoginHandler.getInstance().sendFirstLoginSuccessMsg(index,thread);
                    users.put(index, thread);//主键递增(保存发给客户端
                }else{
                    if (UserManager.getInstance().userKeyIsExist(userKey))
                    {
                        //如果已存在
                        LoginHandler.getInstance().sendLoginSuccessMsg(index,thread);
                    }else {//不存在的话认为是第一次登录
                        index++;
                        //发送第一次登陆成功消息
                        LoginHandler.getInstance().sendFirstLoginSuccessMsg(index,thread);
                        users.put(index, thread);//主键递增(保存发给客户端
                    }
                }
                thread.setKey(index);
            }
        });


//      LoginHandler.getInstance().setSocket(thread);
//      DrawHandler.getInstance().setSocket(thread);

        thread.setOnClientOut(new SocketThread.IOnClientOutListener() {
            @Override
            public void onClientOut() {
                index--;
            }
        });

        return thread;
    }

    public void removeUser(int key)
    {
        if(users.containsKey(key))
        {
            users.remove(key);
        }
    }



    //全员广播
    public  void broadcastAllMsg(ByteArray data,int ignoreKey)
    {
        Iterator<Integer> iter=users.keySet().iterator();
        while(iter.hasNext())
        {
            Integer key=iter.next();
            if(key!=ignoreKey)
            {
                SocketThread thread=users.get(key);
                if(thread!=null&&thread.isConnection()) thread.putMsg(data);
            }
        }
    }
}
 

BaseHandler

 

//发送数据
public void sendMsg(ByteArray data,SocketThread thread)
{
    thread.putMsg(data);;
}
//接收数据
public void recviveMsg(ByteArray data,SocketThread thread)
{

}

DrawHandler

 

public class DrawHandler extends BaseHandler
{
    private static DrawHandler _instance=new DrawHandler();
    public static DrawHandler getInstance()
    {
        return _instance;
    }


    //接收数据
    @Override
    public void recviveMsg(ByteArray data,SocketThread thread)
    {
        //接收到消息转发
        int len=10;
        ByteArray result=new ByteArray();
        result.writeInt(len);
        result.writeByte(Command.DRAW);
        result.writeByte(data.readByte());//类型
        result.writeInt(data.readInt());
        result.writeInt(data.readInt());
        DrawServer.getInstance().broadcastAllMsg(result, thread.getKey());
    }

LoginHandler

 

public class LoginHandler extends BaseHandler {
    private static LoginHandler _instance = new LoginHandler();

    public static LoginHandler getInstance() {
        return _instance;
    }

    //发送第一次登录成功数据
    public void sendFirstLoginSuccessMsg(int key, SocketThread thread) {
        ByteArray data = new ByteArray();
        String userKey = UserManager.getInstance().createUserKey();
        UserManager.getInstance().saveAUserKey(userKey);//储存一个UserKey并且把这个生成的UserKey发送到客户端
        int len = 5 + userKey.length();
        data.writeInt(len);
        data.writeByte(Command.LOGIN);
        data.writeInt(key);
        data.writeByteArray(userKey.getBytes());
        super.sendMsg(data, thread);
    }

    //发送登录成功数据
    public void sendLoginSuccessMsg(int key, SocketThread thread) {
        ByteArray data = new ByteArray();
        int len = 5;
        data.writeInt(len);
        data.writeByte(Command.LOGIN);
        data.writeInt(key);
        super.sendMsg(data, thread);
    }

    //接收数据
    public void recviveMsg(ByteArray data, SocketThread thread) {
        try {
            byte cmd = data.readByteArray(0, 1)[0];
            String userKey = new String(data.readByteArray(1, 36));
            switch (cmd) {
                case Command.LOGIN:
                    doLogin(userKey);
                    break;
                case Command.LOGIN_OUT://登出操作,需要把储存的用户主键清除

                    break;
            }
        } catch (Exception e) {

        }

    }

    /**
     * 做登录操作
     */
    private void doLogin(String userKey) {
        if (mIOnClientLoginListener != null) {
            mIOnClientLoginListener.onLogin(userKey);
        }
    }

    private IOnClientLoginListener mIOnClientLoginListener;

    public void setOnClientLogin(IOnClientLoginListener onClientLogin) {
        mIOnClientLoginListener = onClientLogin;
    }

    interface IOnClientLoginListener {
        void onLogin(String userKey);
    }
}

SocketThread

 

public class SocketThread extends Thread
{
    private Socket msocket;
    private DataOutputStream out = null;
    private boolean isConnection = false;
    private int key;// 客户端和服务器通信标示
    private BaseHandler handler;

    public BaseHandler getHandler() {
        return handler;
    }

    public void setHandler(BaseHandler handler) {
        this.handler = handler;
    }

    private ArrayList<ByteArray> msg = new ArrayList<ByteArray>();

    @Override
    public void run() {
        isConnection = true;
        while (isConnection) {
            try {
                // 读取
                ByteArray result = readSocketData();
                if (result != null) {
                    byte cmd = result.readByte();// 命令号
                    switch (cmd) {
                        case Command.LOGIN:
                            LoginHandler.getInstance().recviveMsg(result, this);
                            break;
                        case Command.DRAW:
                            DrawHandler.getInstance().recviveMsg(result, this);
                            break;
                        case Command.LOGIN_OUT:
                            LoginHandler.getInstance().recviveMsg(result, this);
                            break;
                    }
                }
                // --------------------------
                // 发送
                while (msg.size() > 0) {
                    sendMsg(msg.remove(0));
                }

                Thread.sleep(17);
            } catch (Exception e) {
                breakClient();
            }
        }
    }

    // 放入发送队列
    public void putMsg(ByteArray data) {
        msg.add(data);
    }

    // 向客户端推送消息
    private void sendMsg(ByteArray msg) {
        try {
            out = new DataOutputStream(msocket.getOutputStream());
            byte[] b = msg.toByteArray();
            out.write(b);
            out.flush();
        } catch (IOException e) {
            breakClient();
        }
    }

    // 客户端断开,移除用户连接
    private void breakClient() {
        isConnection = false;
        System.out.println("客户端--" + getKey() + "--断开");
        DrawServer.getInstance().removeUser(getKey());
        try {
            out.close();
            msocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 读取一个数据包
    private ByteArray readSocketData() {
        ByteArray bytearr = null;
        DataInputStream input;
        try {
            input = new DataInputStream(msocket.getInputStream());
            if (input.available() > 0) {
                int len = input.readInt();// 数据长度
                byte[] bytes = new byte[len];
                input.read(bytes, 0, len);
                bytearr = new ByteArray(bytes);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bytearr;
    }

    public boolean isConnection() {
        return isConnection;
    }

    public SocketThread(Socket socket) {
        this.msocket = socket;
    }

    public int getKey() {
        return key;
    }

    public void setKey(int key) {
        this.key = key;
    }

    private IOnClientOutListener mOnClientOutListener;

    public void setOnClientOut(IOnClientOutListener onClientOut)
    {
        mOnClientOutListener = onClientOut;
    }

    interface IOnClientOutListener{
        void onClientOut();
    }

}

 

UserManager

 

 

public class UserManager {

    private static UserManager _instance;

    private static ArrayList<String> userKeys;

    private UserManager()
    {
    }

    public static UserManager getInstance()
    {
        if (_instance == null)
        {
            synchronized (UserManager.class)
            {
                if (_instance == null)
                {
                    _instance = new UserManager();
                }
            }
        }

        if (userKeys == null)
        {
            createUserKeyList();
        }

        return _instance;
    }

    private static void createUserKeyList()
    {
        synchronized (UserManager.class)
        {
            if (userKeys == null)
            {
                userKeys = new ArrayList<String>();
            }
        }
    }

    public ArrayList<String> getAllUserKey()
    {
        return userKeys;
    }

    /**
     * 保存一个用户主键
     * @param userKey
     */
    public ArrayList<String> saveAUserKey(String userKey)
    {
        userKeys.add(userKey);

        return userKeys;
    }

    /**
     * 移除一个用户主键
     * @param userKey
     * @return
     */
    public ArrayList<String> removeAUserKey(String userKey)
    {
        userKeys.remove(userKey);

        return userKeys;
    }

    /**
     * 生成一个用户主键
     * @return
     */
    public String createUserKey()
    {
        return UUID.randomUUID().toString();
    }

    /**
     * 该userKey是否存在
     * @param userKey
     * @return
     */
    public boolean userKeyIsExist(String userKey)
    {
        boolean isExist = false;
        int leg = userKeys.size();

        for (int i = 0; i < leg; i++) {
            if (userKey.equals(userKeys.get(i)))
            {
                isExist = true;
            }
        }
        return isExist;
    }
}

记住运行Android项目的时候要把NetWorkMessage的Socket连接的IP改成你自己电脑,然后Java项目也需要先跑起来,否则的话Socket连接不上,没有指令返回来,手机端是做不了任何操作的!!

 

源码下载:https://download.csdn.net/download/zhaohui_android/10726142

 

如果有问题请留言!!!

 

 
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 24
    评论
软件介绍: ArrayNetworksL3Setu是移动代理点客户端软件,也就是常说的那个红A。需要安装这个软件后才能登陆。BOSS 客户端更新说明为了解决现有BOSS系统BUG,现在需要升级各代办点终端的SSL 的插件,具体插件步骤如下:1.将附件中名称为:“ArrayNetworksL3OnlyWebSetup.zip”的安装包拷贝到代办终端上。 2.在代办终端上解压该文件3.点击“setup.exe”4.一步步安装首先remove现有的插件。点击“next”,点击“finish”,再点击“setup.exe”,点击“finish”完成安装。完成后开始使用,打开IE浏览器。输入移动 IP地址。IE版本可能会出现,点击“允许”,当右下角出现“A” 上面出现8.4.6.80确认为新的插件版本。出现红A,没有任何报错就表示安装正常。-----------------------------------------------------------------------------------------------------如果安装有问题或者不能正常访问,请单独安装客户端。安装的文件名称ArrayNetworksL3SetupX32.zip,ArrayNetworksL3SetupX64.zip请对应系统的版本安装1查看自己的系统的版本,32位,64位2.“计算机”-->“属性”查看自己的是32位的还是64位的操作系统。请对应版本安装。4.安装客户端软件的步骤,首先解压文件。点击 “setup.exe”安装完成。打开IE登陆SSL 如重启失败请重置浏览器的高级设置。点击---“还远高级设置”---“确定”再次登陆
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值