에몽이

1:다 채팅 본문

android

1:다 채팅

ian_hodge 2016. 12. 28. 19:50

단일 PC서버에 다수의 Android Device가 접속하여 채팅하는 프로젝트입니다

최대 접속가능한 Android Device의 갯수는 확인되지않았지만

개인적으로 3대의 Android Device도 가능함을 확인했습니다.

각각 접속되어있는 Device들은 Mac주소를이용하여 구분이되도록했고

접속자수와 퇴장시메세지등등 아직 구현되지않은 기능들은 차후 열심히공부해서

변경후 업데이트하겠습니다.

Mac주소를 받아오기위해서는 wifimanager클래스가필요한데

그부분에대해서는 따로 작성하겠습니다.

저도 독학중이기도하고 부족함이많아서 감안하시고 입맛에맞게참고만해주시기바랍니다.

 

Server.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
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
 
public class SocketClient {
 
    HashMap<String, DataOutputStream> clients;
    private ServerSocket ServerSocket = null;
 
    public static void main(String[] args) {
        new SocketClient().start();
    }
 
    public SocketClient() {
 
        // 연결부 hashmap 생성자(Key, value) 선언
        clients = new HashMap<String, DataOutputStream>();
        // clients 동기화
        Collections.synchronizedMap(clients);
    }
 
    private void start() {
        
        // Port 값은 편의를위해 5001로 고정 (Random값으로 변경가능)
        int port = 5001;
        Socket socket = null;
 
        try {
            // 서버소켓 생성후 while문으로 진입하여 accept(대기)하고 접속시 ip주소를 획득하고 출력한뒤
            // MultiThread를 생성한다.
            ServerSocket = new ServerSocket(port);
            System.out.println("접속대기중");
            while (true) {
                socket = ServerSocket.accept();
                InetAddress ip = socket.getInetAddress();
                System.out.println(ip + "  connected");
                new MultiThread(socket).start();
            }
        } catch (IOException e) {
            System.out.println(e);
        }
    }
 
    class MultiThread extends Thread {
 
        Socket socket = null;
 
        String mac = null;
        String msg = null;
 
        DataInputStream input;
        DataOutputStream output;
 
        public MultiThread(Socket socket) {
            this.socket = socket;
            try {
                // 객체를 주고받을 Stream생성자를 선언한다.
                input = new DataInputStream(socket.getInputStream());
                output = new DataOutputStream(socket.getOutputStream());
            } catch (IOException e) {
            }
        }
 
        public void run() {
 
            try {
                // 접속된후 바로 Mac 주소를 받아와 출력하고 clients에 정보를 넘겨주고 클라이언트에게 mac주소를보낸다.
                mac = input.readUTF();
                System.out.println("Mac address : " + mac);
                clients.put(mac, output);
                sendMsg(mac + "   접속");
 
                // 그후에 채팅메세지수신시
                while (input != null) {
                    try {
                        String temp = input.readUTF();
                        sendMsg(temp);
                        System.out.println(temp);
                    } catch (IOException e) {
                        sendMsg("No massege");
                        break;
                    }
                }
            } catch (IOException e) {
                System.out.println(e);
            }
        }
 
        // 메세지수신후 클라이언트에게 Return 할 sendMsg 메소드
        private void sendMsg(String msg) {
 
            // clients의 Key값을 받아서 String 배열로선언
            Iterator<String> it = clients.keySet().iterator();
 
            // Return 할 key값이 없을때까지
            while (it.hasNext()) {
                try {
                    OutputStream dos = clients.get(it.next());
                    // System.out.println(msg);
                    DataOutputStream output = new DataOutputStream(dos);
                    output.writeUTF(msg);
 
                } catch (IOException e) {
                    System.out.println(e);
                }
            }
        }
    }
}
cs

 

 

 

Client.java (Android)

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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
package com.example.sockettest_1;
 
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.Socket;
import java.util.LinkedList;
 
import android.app.Activity;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
 
public class MainActivity extends Activity {
 
    // private static int port = 5001;
    // private static final String ipText = "192.168.0.7"; // IP지정으로 사용시에 쓸 코드
    String streammsg = "";
    TextView showText;
    Button connectBtn;
    Button Button_send;
    EditText ip_EditText;
    EditText port_EditText;
    EditText editText_massage;
    Handler msghandler;
 
    SocketClient client;
    ReceiveThread receive;
    SendThread send;
    Socket socket;
 
    PipedInputStream sendstream = null;
    PipedOutputStream receivestream = null;
 
    LinkedList<SocketClient> threadList;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        ip_EditText = (EditText) findViewById(R.id.ip_EditText);
        port_EditText = (EditText) findViewById(R.id.port_EditText);
        connectBtn = (Button) findViewById(R.id.connect_Button);
        showText = (TextView) findViewById(R.id.showText_TextView);
        editText_massage = (EditText) findViewById(R.id.editText_massage);
        Button_send = (Button) findViewById(R.id.Button_send);
        threadList = new LinkedList<MainActivity.SocketClient>();
 
        ip_EditText.setText("192.168.0.7");
        port_EditText.setText("5001");
 
        // ReceiveThread를통해서 받은 메세지를 Handler로 MainThread에서 처리(외부Thread에서는 UI변경이불가)
        msghandler = new Handler() {
            @Override
            public void handleMessage(Message hdmsg) {
                if (hdmsg.what == 1111) {
                    showText.append(hdmsg.obj.toString() + "\n");
                }
            }
        };
 
        // 연결버튼 클릭 이벤트
        connectBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {            
                //Client 연결부
                client = new SocketClient(ip_EditText.getText().toString(),
                        port_EditText.getText().toString());
                threadList.add(client);
                client.start();
            }
        });
 
        //전송 버튼 클릭 이벤트
        Button_send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                
                //SendThread 시작
                if (editText_massage.getText().toString() != null) {
                    send = new SendThread(socket);
                    send.start();
 
                    //시작후 edittext 초기화
                    editText_massage.setText("");
                }
            }
        });
    }
 
    class SocketClient extends Thread {
        boolean threadAlive;
        String ip;
        String port;
        String mac;
 
        //InputStream inputStream = null;
        OutputStream outputStream = null;
        BufferedReader br = null;
 
        private DataOutputStream output = null;
 
        public SocketClient(String ip, String port) {
            threadAlive = true;
            this.ip = ip;
            this.port = port;
        }
 
        @Override
        public void run() {
 
            try {
                // 연결후 바로 ReceiveThread 시작
                socket = new Socket(ip, Integer.parseInt(port));
                //inputStream = socket.getInputStream();
                output = new DataOutputStream(socket.getOutputStream());
                receive = new ReceiveThread(socket);
                receive.start();
                
                //mac주소를 받아오기위해 설정
                WifiManager mng = (WifiManager) getSystemService(WIFI_SERVICE);
                WifiInfo info = mng.getConnectionInfo();
                mac = info.getMacAddress();
                
                //mac 전송
                output.writeUTF(mac);
 
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
 
    class ReceiveThread extends Thread {
        private Socket socket = null;
        DataInputStream input;
 
        public ReceiveThread(Socket socket) {
            this.socket = socket;
            try{
                input = new DataInputStream(socket.getInputStream());            
            }catch(Exception e){            
            }
        }
        // 메세지 수신후 Handler로 전달
        public void run() {
            try {
                while (input != null) {
                    
                    String msg = input.readUTF();
                    if (msg != null) {
                        Log.d(ACTIVITY_SERVICE, "test");
 
                        Message hdmsg = msghandler.obtainMessage();
                        hdmsg.what = 1111;
                        hdmsg.obj = msg;
                        msghandler.sendMessage(hdmsg);
                        Log.d(ACTIVITY_SERVICE,hdmsg.obj.toString());                    
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
 
    class SendThread extends Thread {
        private Socket socket;
        String sendmsg = editText_massage.getText().toString();
        DataOutputStream output;
 
        public SendThread(Socket socket) {
            this.socket = socket;
            try {
                output = new DataOutputStream(socket.getOutputStream());
            } catch (Exception e) {
            }
        }
 
        public void run() {
 
            try {
                
                // 메세지 전송부 (누군지 식별하기위한 방법으로 mac를 사용)
                Log.d(ACTIVITY_SERVICE, "11111");
                String mac = null;
                WifiManager mng = (WifiManager) getSystemService(WIFI_SERVICE);
                WifiInfo info = mng.getConnectionInfo();
                mac = info.getMacAddress();
 
                if (output != null) {
                    if (sendmsg != null) {
                        output.writeUTF(mac + "  :  " +sendmsg);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NullPointerException npe) {
                npe.printStackTrace();
 
            }
        }
    }
}
 
cs

 

 

Client.xml

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
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >
 
        <EditText
            android:id="@+id/ip_EditText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="IP주소를입력하세요" />
 
        <EditText
            android:id="@+id/port_EditText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="PORT주소를입력하세요" />
    </LinearLayout>
 
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center" >
 
        <Button
            android:id="@+id/connect_Button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="연결" />
    </RelativeLayout>
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="horizontal" >
 
        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent" >
 
            <TextView
                android:id="@+id/showText_TextView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="" />
        </ScrollView>
    </LinearLayout>
 
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
 
        <EditText
            android:id="@+id/editText_massage"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="0.5"
            android:ems="10"
            android:hint="메세지를작성해주세요" />
 
        <Button
            android:id="@+id/Button_send"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            android:text="전송" />
    </LinearLayout>
 
</LinearLayout>
 
cs

출처:http://ginjo.tistory.com/2


Comments