티스토리 뷰

 

지금부터는 정신 바짝 차리고 집중하셔야 합니다 ! 

코드에도 주석을 자세히 달아 놓을테니 차근차근 따라오세요 ! 

 

  1) 먼저 어떻게 돌아가는지 설명해 드리겠습니다.


: 제일 처음에 보여드렸던 전체 그림을 보시면서 따라오세요! 
선행 지식 ① 
-> Java에서와 다르게 Android에서는 Network를 사용할때 무조건 thread안에서 처리하도록 되어 있습니다. 
( cf) 네트워크는 병목현상을 일으킬 가능성이 있기때문에 진저브레드 버젼(2.3v)부터 자체적으로 strict mode라는 규제를 걸었습니다.)
앞에서도 언급되었듯이 client에는 총 2개의 thread가 돌아갑니다! ( + Network를 위한 thread 1개 더! )
     1) ConnectThread  - 네트워크 연결을 위한 thread입니다. 
     2) ClientSender - Server로 메시지를 보낼 thread이고, 
     3) ClientReceiver - 메시지를 받을 thread입니다. 
( cf) 사실 android는 thread를 사용하기 위한 몇가지 방법이 있는데요, 원래는 네트워크 연결을 하는 경우에는 'AsyncTask'라는 클래스를 사용하는걸 권장합니다. )

 

 

 2) MainActivity 수정


 < 선행 지식 ② 
-> Android에서는 UI component를 수정하려면 무조건 main thread(UI thread)를 사용해야 합니다. 
 ( cf) main thread의 주로 View를 담당하는 일에 열중하고, 나머지 연산처리 등은 작업 thread에게 맡기는게 바람직합니다.
 
  1) setText()  sendMsg() 사용 
 : 우리는 이전 UI를 만드는 예제에서 textView에 setText()를 하는 방법으로 뿌려줬었는데요. 
사실 멀티 채팅 전체적인 흐름으로 보면 Client가 직접 뿌리는게 아니라, Server에서 보내주는 data를 뿌리도록 해야 합니다.  
그렇기 때문에, setText()하는 동작을 새로운 메소드를 정의해 Server로 메시지를 보내는 동작으로 바꿔 줄겁니다.
 
  2) typeMsg() 추가
: 이 메소드는 ClientReceiver thread에서 call되는데요, 
 작업thread안에서 UI에 접근하지 못하기 때문에 별도의 메소드를 구성했습니다. 

 

onCreate()내에 Client연결

1
2
3
4
5
/**
  * client 연결을 합니다.
  */
client = new ChatClient(this);
client.startClient();
cs

 

sendMsg() 사용

1
2
3
4
5
6
7
8
9
public void onSendBtnClicked(View v)
    {
 
        String msg = inputText.getText().toString();
        inputText.setText("");
 
        // ChatClient가 메시지를 server로 보낼수 있도록 msg를 날려줍니다.
        client.sendMsg(msg);
    }
cs

 

typeMsg() 추가

1
2
3
4
5
// Client에서 msg를 받아서 뿌리는 메소드입니다.
    public void typeMsg(String msg)
    {
        inputText.setText(msg);
    }
cs
 3) ChatClient 코드
   : Network 관련 부분은 주석으로 달아놓겠습니다. 

 


ChatClient.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package com.example.kbpark.blogmultichatclient;
 
import android.content.Context;
import android.os.Handler;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
 
/**
 * Created by KBPark on 2016. 5. 28..
 */
public class ChatClient
{
    public static final String SERVER_IP = "192.168.219.141";
    Context context;
    Handler handler;
 
    String msg;
    String rcvMsg;
 
    ChatClient(Context context)
    {
        this.context = context;
    }
 
    public void startClient()
    {
        handler = new Handler();
 
        ConnectThread thread = new ConnectThread();
        thread.start();
    }
 
 
    // 안드로이드에서는 네트워크 통신을 할때, 반드시 쓰레드로 해야합니다.(아니면 strict mode 위반에 걸림.)
    // + INTERNET permission
    class ConnectThread extends Thread
    {
 
        @Override
        public void run()
        {
 
            try {
                // 1. Socket을 만들고 연결을 요청합니다.
                Socket socket = new Socket(SERVER_IP, 7777);
 
                // 2. inout / output에 해당하는 thread를 각각 만들고 start()합니다
                Thread sender = new Thread(new ClientSender(socket, "유니"));
                Thread receiver = new Thread(new ClientReceiver(socket));
 
                sender.start();
                receiver.start();
 
            }catch(IOException e){
                e.printStackTrace();
            }
 
        }
 
    }
 
    class ClientSender extends Thread
    {
        Socket socket;
        DataOutputStream out;
        String name;
 
        ClientSender(Socket socket, String name)
        {
            this.socket = socket;
            this.name = name;
 
            try
            {
                out = new DataOutputStream(socket.getOutputStream());
 
            }catch (IOException e){
                e.printStackTrace();
            }
        }
 
        @Override
        public void run()
        {
            try {
                // name을 먼저 알려주고 (왜냐면, server측에서 hashmap에 '이름 - output'정보를 미리 저장해두는 구조거든요)
                if(out != null)
                {
                    out.writeUTF(name);
                }
 
                // 메시지를 서버로 보냅니다.(무한루프 돌면서 OutputStream에서 가져올게 있으면, wrtieUTF()를 실행합니다)
                while (out != null)
                {
                    if(msg != null)
                    {
                        out.writeUTF("[" + name + "] : " + msg);
                        msg = null;
                    }
                }
 
            }catch (IOException e){}
        }
    }
 
    class ClientReceiver extends Thread
    {
        Socket socket;
        DataInputStream in;
 
        ClientReceiver(Socket socket)
        {
            try
            {
                this.socket = socket;
                in = new DataInputStream (socket.getInputStream());
 
            }catch (IOException e)
            {
                e.printStackTrace();
            }
        }
 
        @Override
        public void run()
        {
            while (in != null)
            {
                try
                {
                    // outputStream으로 온 데이터를 read합니다
                    rcvMsg = in.readUTF();
 
                }catch (IOException e){}
 
                // 작업 thread 안에서 inputText에 값을 직접 찍어주는건 불가능합니다.
                handler.post(new Runnable() {
                    @Override
                    public void run()
                    {
                        ((MainActivity) context).typeMsg(rcvMsg);
                    }
                });
            }
        }
 
    }
 
    public void sendMsg(String msg)
    {
        this.msg = msg;
    }
 
}
 
cs

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함