特简单, 没有数据库, 还没有处理各种异常。
登录:输入用户名点击的登录即可。
发送消息: 特定格式->toUser:message
1. 服务器:保存在线用户
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
|
public class Online { private static Online mOnline = null ; private LinkedHashMap<String, Socket> mOnlines = new LinkedHashMap<String, Socket>(); private Online() { } public synchronized static Online getInstance() { if ( null == mOnline) { mOnline = new Online(); } return mOnline; } if (!mOnlines.containsKey(key)) { mOnlines.put(key, socket); } } public Socket get(String key) { return mOnlines.get(key); } public void remove(String key) { mOnlines.remove(key); } } |
2. 服务器:一个简单的socket服务器
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
|
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; // login:uid // send:fromuser:touser:message // logout:uid public class Server implements Runnable { private Socket mSocket; private Online mOnline; public Server(Socket socket) { mSocket = socket; mOnline = Online.getInstance(); } @Override public void run() { try { BufferedReader reader = new BufferedReader( new InputStreamReader( mSocket.getInputStream())); String cmd = reader.readLine(); // login if (cmd.startsWith( "login" )) { String userName = cmd.split( ":" )[ 1 ]; mOnline.put(userName, mSocket); System.out.println(userName + " login..." ); PrintWriter writer = new PrintWriter(mSocket.getOutputStream()); writer.println( "success" ); writer.flush(); } else if (cmd.startsWith( "send" )) { System.out.println(cmd); String[] cmds = cmd.split( ":" ); String from = cmds[ 1 ]; Socket to = mOnline.get(cmds[ 2 ]); String msg = cmds[ 3 ]; PrintWriter writer = new PrintWriter(to.getOutputStream()); System.out.println( "rec:" + from + ":" + cmds[ 2 ] + ":" + msg); writer.println( "rec:" + from + ":" + cmds[ 2 ] + ":" + msg); writer.flush(); } else if (cmd.startsWith( "logout" )) { System.out.println(cmd); String user = cmd.split( ":" )[ 1 ]; mOnline.get(user).close(); mOnline.remove(user); PrintWriter writer = new PrintWriter(mSocket.getOutputStream()); writer.println( "success" ); writer.flush(); } } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) throws Exception { ServerSocket server = new ServerSocket( 8888 ); boolean flag = true ; while (flag) { new Thread( new Server(server.accept())).start(); System.out.println( "user in..." ); } server.close(); } } |
3. 客户端登录界面
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
|
public class MainActivity extends Activity { private EditText mUser; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); mUser = (EditText) findViewById(R.id.username); } public void login(View view) { final String userName = mUser.getText().toString().trim(); Login login = new Login(userName); login.setOnLoginListener( new Login.LoginCallback() { @Override public void onLogin( boolean success) { if (success) { Intent intent = new Intent(MainActivity. this , Chat. class ); intent.putExtra( "user" , userName); startActivity(intent); finish(); } else { Toast.makeText(MainActivity. this , "登录失败" , Toast.LENGTH_SHORT).show(); } } }); login.login(); } } |
4. 处理登录
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
|
public class Login { private String mUserName; private LoginCallback mCallback; public Login(String userName) { mUserName = userName; } public void setOnLoginListener(LoginCallback callback) { mCallback = callback; } private Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case Constant.SUCCESS: mCallback.onLogin( true ); break ; case Constant.FAILED: mCallback.onLogin( false ); break ; } }; }; public void login() { new Thread( new Runnable() { @Override public void run() { Socket socket = null ; try { socket = new Socket(); socket.connect( new InetSocketAddress( "192.168.100.100" , 8888 ), 4000 ); PrintWriter writer = new PrintWriter(socket.getOutputStream()); writer.println( "login:" + mUserName); writer.flush(); BufferedReader reader = new BufferedReader( new InputStreamReader(socket.getInputStream())); String line = reader.readLine(); System.out.println(line); if ( "success" .equals(line)) { PConnection.socket = socket; mHandler.sendEmptyMessage(Constant.SUCCESS); } else { mHandler.sendEmptyMessage(Constant.FAILED); } } catch (Exception e) { e.printStackTrace(); } } }).start(); } public interface LoginCallback { public void onLogin( boolean success); } } |
5. 聊天界面
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
|
public class Chat extends Activity { private String mUserName; private EditText mEdit; private ListView mMessage; private ReceiverMessage mRecMessage; private SendMessage mSendMesage; private List<Map<String, String>> mData = new ArrayList<Map<String, String>>(); private MessagesAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.chat_layout); mUserName = getIntent().getStringExtra( "user" ); mEdit = (EditText) findViewById(R.id.edit); mMessage = (ListView) findViewById(R.id.message); mRecMessage = new ReceiverMessage(); mRecMessage.setOnReceiverListener( new RecListener()); mRecMessage.run(); mSendMesage = new SendMessage(); mSendMesage.setOnSendListener( new SendListener()); mAdapter = new MessagesAdapter( this , mData); mMessage.setAdapter(mAdapter); } public void send(View view) { String[] content = mEdit.getText().toString().trim().split( ":" ); mSendMesage.send(mUserName, content[ 0 ], content[ 1 ]); } private class RecListener implements ReceiverMessage.OnReceiverListener { @Override public void onReceiver(String user, String msg) { Map<String, String> temp = new HashMap<String, String>(); temp.put( "user" , user); temp.put( "msg" , msg); temp.put( "pos" , "right" ); mData.add(temp); mAdapter.notifyDataSetChanged(); } } private class SendListener implements SendMessage.OnSendListener { @Override public void onSend(String[] msg) { Map<String, String> temp = new HashMap<String, String>(); temp.put( "user" , "我" ); temp.put( "msg" , msg[ 1 ]); temp.put( "pos" , "left" ); mData.add(temp); mAdapter.notifyDataSetChanged(); } } @Override public boolean onOptionsItemSelected(MenuItem item) { if (R.id.logout == item.getItemId()) { Logout logout = new Logout(); logout.setOnLogoutListener( new Logout.OnLogoutListener() { @Override public void onLogout( boolean success) { if (success) { Toast.makeText(Chat. this , "注销成功" , Toast.LENGTH_SHORT).show(); finish(); } else { Toast.makeText(Chat. this , "注销失败" , Toast.LENGTH_SHORT).show(); } } }); logout.logout(mUserName); } return super .onOptionsItemSelected(item); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return super .onCreateOptionsMenu(menu); } } |
6. 发送消息
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
|
public class SendMessage { private OnSendListener mListener; public void setOnSendListener(OnSendListener listener) { mListener = listener; } private Handler mHandler = new Handler() { public void handleMessage(Message msg) { mListener.onSend((String[]) msg.obj); }; }; // send:from:to:message public void send( final String from , final String to, final String msg) { new Thread( new Runnable() { @Override public void run() { Socket socket = null ; try { socket = new Socket(); socket.connect( new InetSocketAddress( "192.168.100.100" , 8888 ), 4000 ); PrintWriter writer = new PrintWriter(socket.getOutputStream()); writer.println( "send:" + from + ":" + to + ":" + msg); writer.flush(); Message message = mHandler.obtainMessage( Constant.SUCCESS, new String[] {to, msg}); message.sendToTarget(); } catch (Exception e) { } finally { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }).start(); } public interface OnSendListener { public void onSend(String[] msg); } } |
7. 接收消息,死循环,但阻塞,没啥问题
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
|
public class ReceiverMessage { private OnReceiverListener mListener; public void setOnReceiverListener(OnReceiverListener listener) { mListener = listener; } private Handler mHandler = new Handler() { public void handleMessage(Message msg) { String[] cmds = (String[]) msg.obj; mListener.onReceiver(cmds[ 0 ], cmds[ 1 ]); }; }; public void run() { new Thread( new Runnable() { @Override public void run() { try { Socket socket = PConnection.socket; while ( true ) { System.out.println( "wait for message..." ); BufferedReader reader = new BufferedReader( new InputStreamReader(socket.getInputStream())); String line = reader.readLine(); if (line.startsWith( "rec" )) { //rec:fromuser:touser:message String[] cmds = line.split( ":" ); System.out.println(cmds[ 0 ] + ":" + cmds[ 1 ] + ":" + cmds[ 2 ] + ":" + cmds[ 3 ]); Message msg = mHandler.obtainMessage(Constant.SUCCESS, new String[] {cmds[ 1 ], cmds[ 3 ]}); msg.sendToTarget(); } } } catch (Exception e) { e.printStackTrace(); } } }).start(); } public interface OnReceiverListener { public void onReceiver(String user, String msg); } } |
8. 注销登录
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
|
public class Logout { public OnLogoutListener mListener; public void setOnLogoutListener(OnLogoutListener listner) { mListener = listner; } private Handler mHandler = new Handler() { public void handleMessage(Message msg) { if (Constant.SUCCESS == msg.what) { mListener.onLogout( true ); } else { mListener.onLogout( false ); } }; }; public void logout( final String user) { new Thread( new Runnable() { @Override public void run() { try { Socket socket = new Socket(); socket.connect( new InetSocketAddress( "192.168.100.100" , 8888 ), 4000 ); PrintWriter writer = new PrintWriter(socket.getOutputStream()); writer.println( "logout:" + user); writer.flush(); BufferedReader reader = new BufferedReader( new InputStreamReader(socket.getInputStream())); if ( "success" .equals(reader.readLine())) { PConnection.socket = null ; mHandler.sendEmptyMessage(Constant.SUCCESS); } else { mHandler.sendEmptyMessage(Constant.FAILED); } } catch (Exception e) { e.printStackTrace(); } } }).start(); } public interface OnLogoutListener { public void onLogout( boolean success); } } |
9. 存放登录后的socket,在发送消息和接收消息时使用该socket
1
2
3
|
public class PConnection { public static Socket socket; } |
希望本文所述对大家学习有所帮助。