Android Sokect 一对多~ 服务端对多个客户端(个人笔记)

最近公司要求做个小工具 要求三台手机同时操作做某个事情——Sokect就简单粗暴可实现

一个服务端 两个客户端就欧了

服务端:

import android.content.Context;
import android.util.Log;
import android.widget.Toast;

import com.eggplant.virgo.features.main.FaceMainNewActivity;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;

import static com.eggplant.virgo.features.sokect.tcp.SockeState.SERVICE_ADDCLIENT;
import static com.eggplant.virgo.features.sokect.tcp.SockeState.SERVICE_DISCONNECT;
import static com.eggplant.virgo.features.sokect.tcp.SockeState.STARTSERVICE;
import static com.eggplant.virgo.features.sokect.tcp.SockeState.STARTSERVIC_ERROR;

public class ServerListener {
    private static ServerListener minstace;
    private ServerListener () {}
    public static ServerListener getInstance() {
        if (minstace == null) {
            synchronized (ServerListener.class) {
                if (minstace == null) {
                    minstace = new ServerListener();
                }
            }
        }
        return minstace;

    }
  private static ServerSocket serverSocket;
    public boolean isOpen() {
        if (serverSocket != null) {
            return !serverSocket.isClosed();
        }
        return false;
    }

//启动服务端

    public void startService() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    serverSocket = new ServerSocket(8080);
                    while (true) {
                        Log.d("skj", "========:启动服务"+  serverSocket);
                        EventBus.getDefault().post(new SockeState(STARTSERVICE));
                        Socket socket = serverSocket.accept();
                        ChartSocket cs = new ChartSocket(socket);
                        cs.start();
                        ChatManager.getChatManager().add(cs);
                        EventBus.getDefault().post(new SockeState(SERVICE_ADDCLIENT));

                    }
                } catch (IOException e) {
                    Log.d("skj", "========:服务开启异常");
                    EventBus.getDefault().post(new SockeState(STARTSERVIC_ERROR, e.toString()));
                    e.printStackTrace();
                }
            }
        }).start();
    }

}

-------------------------------------------------------------------------------------------------------------
import android.util.Log;

import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import static com.eggplant.virgo.features.main.FaceMainNewActivity.HEART;

public class ChatManager {

    /**
     * @param
     */
    private ChatManager() {
    }

    private static final ChatManager cm = new ChatManager();

    public static ChatManager getChatManager() {
        return cm;
    }

    Vector<ChartSocket> vector = new Vector<ChartSocket>();

    public void add(ChartSocket cs) {
        vector.add(cs);
        cs.out(HEART);//连接进来第一时间发送心跳包
        sendBeatData();
    }

    public void publish(ChartSocket cs, String out) {
        for (int i = 0; i < vector.size(); i++) {//遍历所有de chartsocket
            ChartSocket csChartSocket = vector.get(i);//获取循环中的第I个对象  telnet localhost 12345
            if (!cs.equals(csChartSocket)) {//除了本身
                csChartSocket.out(out);
                System.out.println("将信息发送给所有客户 调用pulish:  " + out);

            }
        }
    }

    /**
     * 服务器给所有用户发送信息
     */
    public void servicePublish(String out) {
        for (int i = 0; i < vector.size(); i++) {//遍历所有de chartsocket
            ChartSocket csChartSocket = vector.get(i);//获取循环中的第I个对象  telnet localhost 12345
            csChartSocket.out(out);


        }
    }

    /*倒计时Timer发送心跳包*/
    private Timer timer;
    private TimerTask task;
    private int heartCycle = 10;

    /*定时发送数据*/
    private void sendBeatData() {
        if (timer == null) {
            timer = new Timer();
        }
        if (task == null) {
            task = new TimerTask() {
                @Override
                public void run() {
                    try {
                        Log.i("skj", "服务器发送心跳包");
                        servicePublish(HEART);
                    } catch (Exception e) {
                        e.printStackTrace();

                    }
                }
            };
            timer.schedule(task, 0, 1000 * heartCycle);
        }


    }

}

---------------------------------------------------------------------------------------------------------------------------------------------------------------------

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
public class ChartSocket extends Thread {
    Socket socket;
    BufferedWriter bw;
    BufferedReader br;
    public ChartSocket(Socket s) {
        this.socket = s;
        try {
            bw = new BufferedWriter(new OutputStreamWriter(
                    socket.getOutputStream(), "utf-8"));
            br = new BufferedReader(new InputStreamReader(
                    socket.getInputStream(), "utf-8"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void out(String out) {
        try {
            bw.write(out + "\n");// 必须要加换行符号,不然数据发不出去
            bw.flush();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void run(){
        try {
//          BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
            String line=null;
            while((line=br.readLine())!=null){//reaadline是个阻塞函数  没有读取到会一直处于阻塞状态
                System.out.println("读取到了信息");
                System.out.println("客户端发来数据:"+line);
//                ChatManager.getChatManager().publish(this, line);
                System.out.println("写入了信息");
            }
            br.close();
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

==========================================================================

客户端代码:

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;

import org.greenrobot.eventbus.EventBus;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Timer;
import java.util.TimerTask;

import static com.eggplant.virgo.features.main.FaceMainNewActivity.HEART;
import static com.eggplant.virgo.features.sokect.tcp.SockeState.SERVICE_DISCONNECT;

public class SokectClient {
    private static SokectClient minstace;
    private int heartCycle = 10;

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

    }

    Socket socket = null;
    BufferedReader reader = null;
    BufferedWriter writer = null;
    AsyncTask<Void, String, Void> read;
    private Listener mListener;
    private long lastService;
    private boolean isClose = true;
    private Context mContext;
    private String mIp;

    public void setListener(Listener listener, Context context) {
        this.mListener = listener;
        this.mContext = context;
    }

    /**
     * 连接服务端
     */
    public void connect(final String ip) {
        this.mIp = ip;
        if (read!=null){
            recovery();
        }
        read = new AsyncTask<Void, String, Void>() {
            protected Void doInBackground(Void... params) {
                try {
                    socket = new Socket(ip, 8080);
                    writer = new BufferedWriter(new OutputStreamWriter(
                            socket.getOutputStream(), "utf-8"));
                    Log.e("skj", "writerwriterwriterwriter");

                    reader = new BufferedReader(
                            new InputStreamReader(
                                    socket.getInputStream(), "utf-8"));
                    Log.e("skj", "dream......................");
                    publishProgress("@Sucess");
                    sendBeatData();
                } catch (UnknownHostException e1) {
                    Log.d("skj", "=====:无法建立链接");
                    mListener.dataListener("103");
                    EventBus.getDefault().post(new SockeState(103, e1.toString()));
                    e1.printStackTrace();
                } catch (IOException e1) {
                    Log.d("skj", "=====:无法建立链接");
                    EventBus.getDefault().post(new SockeState(103, e1.toString()));
                    mListener.dataListener("103");
                    e1.printStackTrace();
                }
                try {
                    String line;
                    while ((reader != null) && (line = reader.readLine()) != null) {
                        publishProgress(line);
                        Log.e("skj", " readling()");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }

                return null;
            }

            @Override
            protected void onProgressUpdate(String... values) {
                mListener.dataListener(values[0]);
                if (values[0].equals("@Sucess")) {
                    isClose = false;
                    lastService = System.currentTimeMillis();
                    Toast.makeText(mContext, "建立链接",
                            Toast.LENGTH_SHORT).show();
                } else {
                    isClose = false;
//                    Toast.makeText(context, "收到数据!",
//                            Toast.LENGTH_SHORT).show();
                    Log.d("skj", "服务器信息:" + values[0] + "\n");
                    if (values[0] != null && values[0].equals(HEART)) {

                        Log.d("skj", "收到心跳包:" + values[0] + "\n");
                        lastService = System.currentTimeMillis();
                    }

                }
            }

        };
        read.execute();


    }

    public boolean isClose() {
        if (socket != null) {
            if (socket.isClosed()) {
                return socket.isClosed();
            } else {
                return isClose;
            }
        } else {
            return isClose;
        }
    }

    /*倒计时Timer发送心跳包*/
    private Timer timer;
    private TimerTask task;

    /*定时发送数据*/
    private void sendBeatData() {
        if (timer == null) {
            timer = new Timer();
        }

        if (task == null) {
            task = new TimerTask() {
                @Override
                public void run() {
                    try {
                        Log.i("skj", "发送心跳包");
                        /*这里的编码方式根据你的需求去改*/
                        writer.write("heart" + "\n");
                        writer.flush();
                        if ((System.currentTimeMillis() - lastService) > 2000 * heartCycle) {
                            EventBus.getDefault().post(new SockeState(SERVICE_DISCONNECT));
                            Log.e("skj", "服务器连接断开,正在重连");
                            isClose = true;
                            recovery();
                            connect(mIp);
                        }
                    } catch (Exception e) {
                        /*发送失败说明socket断开了或者出现了其他错误*/
                        EventBus.getDefault().post(new SockeState(SERVICE_DISCONNECT));
                        isClose = true;
                        Log.e("skj", "连接断开,正在重连");
                        /*重连*/
                        recovery();
                        connect(mIp);
                        e.printStackTrace();

                    }
                }
            };
        }

        timer.schedule(task, 0, 1000 * heartCycle);
    }

    private void recovery() {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
        if (task != null) {
            task.cancel();
            task = null;
        }
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (writer != null) {
            try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (read.getStatus() == AsyncTask.Status.RUNNING ||
                read.getStatus() == AsyncTask.Status.PENDING) {
            read.cancel(true);
            read = null;
        }


    }


    public interface Listener {

        void dataListener(String l);
    }

}

 

获取本机IP地址:

public class IPUtil {
    public static String formatIpAddress(int ipAdress) {

        return (ipAdress & 0xFF) + "." + ((ipAdress >> 8) & 0xFF) + "." + ((ipAdress >> 16) & 0xFF) + "."
                + (ipAdress >> 24 & 0xFF);
    }

    //获取本地IP函数
    public static String getLocalIPAddress() {
        //获取wifi服务  
        WifiManager wifiManager = (WifiManager) VirgoApp.getInstance().getApplicationContext()
                .getSystemService(Context.WIFI_SERVICE);
        //判断wifi是否开启  
        if (!wifiManager.isWifiEnabled()) {
            wifiManager.setWifiEnabled(true);
        }
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        int ipAddress = wifiInfo.getIpAddress();
        return formatIpAddress(ipAddress);
    }
}

UI比较简单 

Android Sokect 一对多~ 服务端对多个客户端(个人笔记)

转载:https://blog.csdn.net/Larry_794204525/article/details/53842951