android Soket를 활용한 통신 - Client

Socket에서 Server에 이어 Client를 진행 하겠습니다.

android에서 개발을 진행 하면 Server를 만들일은 특수한 경우 아니면 없다고 생가 할수 있습니다.
Client의 경우 필요에 따라 만들어 써야 하는 경우가 있습니다.
그렇기 때문에 직접 구현 하지 않더라도 Socket.io처럼 잘되어 있는 라이브러리도 존재 하기는 합니다.
하지만 여기서는 Server와 Client에 대한 구현 부분을 알아보는데 의미를 두어 Client도 직접 구현 하겠습니다.

android 네트워크 통신에서 가장 기본이면서 중요한 부분은 무엇일까요?
당연히 비동기 통신을 통한 UI쓰레드에서 UI 갱신 일 것입니다.
Socket 통신도 당연히 이부분은 해당 되며 통신 모든 부분에서 비동기 처리 및 UI  갱신은 UI쓰레드에서
진행 되어야 합니다.
저는 개인적으로runOnUiThread보다 AsyncTask를 활용하는 것을 선호하기 때문에 Client 부분도
AsyncTask를 이용 하겠습니다.


public interface OnSocketConnectCallback{
        public void onConnect();
        public void onFail(String msg);
    }

    public interface OnSocketListenCallback{
        public void onListen(String data);
        public void onError(String msg);
    }

    public interface OnSocketSendCallback{
        public void onSendComplete();
        public void onFail(String msg);
    }

    private Socket client = null;

    private DataInputStream clientIn;
    private DataOutputStream clientOut;

    private boolean isStop = true;

    private OnSocketConnectCallback connectCallback;
    private ArrayList<OnSocketListenCallback> arraylistenCallback = new ArrayList<>();
    private OnSocketSendCallback sendCallback;
기본 적으로 선언한 멤버 변수와 callback 입니다.
개인적으로 필요하다 생각하여 callback들을 만든 것이니 크게 신경 쓸 필요는 없습니다.

public void connect(final String ip, final int port)
    {
        new AsyncTask<Void, String, Void>() {

            String sConnectError = "";
            String sClientError = "";

            @Override
            protected Void doInBackground(Void... voids) {


                try {

                    client = new Socket(ip, port);
                    clientOut = new DataOutputStream(client.getOutputStream());
                    clientIn = new DataInputStream(client.getInputStream());

                    if(connectCallback != null)
                    {
                        connectCallback.onConnect();
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                    sConnectError = e.getMessage();
                    return null;
                }

                try {

                    isStop = false;

                    while (isStop == false)
                    {
                        String sMsg = clientIn.readUTF();

                        if(TextUtils.isEmpty(sMsg) == false)
                        {
                            publishProgress(sMsg);
                        }
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                    sClientError = e.getMessage();
                }

                return null;
            }

            @Override
            protected void onProgressUpdate(String... values) {
                super.onProgressUpdate(values);

                if(values == null)
                {
                    return;
                }

                for(int i = 0; i < values.length; i++)
                {
                    if(arraylistenCallback != null)
                    {
                        for(int j = 0 ; j < arraylistenCallback.size(); j++)
                        {
                            arraylistenCallback.get(j).onListen(values[i]);
                        }
                    }

                }

            }

            @Override
            protected void onPostExecute(Void result) {
                super.onPostExecute(result);

                if(TextUtils.isEmpty(sConnectError) == false
                        && connectCallback != null)
                {
                    connectCallback.onFail(sConnectError);
                }

                else if(TextUtils.isEmpty(sClientError) == false
                        && arraylistenCallback != null)
                {
                    for(int j = 0 ; j < arraylistenCallback.size(); j++)
                    {
                        arraylistenCallback.get(j).onError(sClientError);
                    }
                }
            }
        }.execute();

    }
Client Socket을 연결하고 Server의 메세지를 기다리는 것을 구현한 것 입니다.
Server와 기다리는 부분이 크게 다르지 않다는 것을 알수 있습니다.
메세지가 오면 AsycnTask에서 publishProgress를 통하여 onProgressUpdate함수를 호출 하여
메세지를 UI쓰레드에서 처리 할 수 있도록 하였습니다.

public void sendMessage(final String sMsg)
    {
        if(client == null)
        {
            return;
        }

        new AsyncTask<Void, Integer, Void>() {

            private String sErr = "";

            private ArrayList<String> arrayMsg = new ArrayList<>();

            @Override
            protected Void doInBackground(Void... voids) {


                try {

                    clientOut.writeUTF(sMsg);

                } catch (IOException e) {
                    e.printStackTrace();
                    sErr = e.getMessage();

                }

                return null;
            }


            @Override
            protected void onPostExecute(Void result) {
                super.onPostExecute(result);

                if(sendCallback != null)
                {
                    if(TextUtils.isEmpty(sErr) == true)
                    {
                        sendCallback.onSendComplete();
                    }
                    else
                    {
                        sendCallback.onFail(sErr);
                    }

                }

            }
        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

    }
메세지 보내는 부분입니다.
이부분도 Server와 별다른것은 없습니다.

Socket을 종료하는 부분도 close함수를 호출 하면 되기 때문에 따로 언급하지는 않겠습니다.

2회에 걸쳐 Server, Client를 만들어 Socket통신 하는 부분을 구현 하였습니다.
실제 프로젝트를 위해서 구현한다면 네트워크등의 다양한 환경을 고려하여
더많은 처리가 들어가야 할 것입니다.
기타 처리를 쉽게 해주기 위한 잘 제공되어 있는 라이브러리도 많지만 Socket통신의 기본적인
동작 원리를 알기 위해 이번 포스트를 진행 하였습니다.




댓글

댓글 쓰기

주간 인기글

[정보] 인스타그램은 당신의 소리를 '듣고' 있을 수도 있습니다

남산 케이블카 이야기

[Angular] 모델, 값이 바뀌었는데 화면 template 이 업데이트 되지 않을 때 조치 팁

안드로이드에서 당겨서 새로고침(SwipeRefreshLayout) 쉽게 구현하기

Java8 Stream 가이드