特简单, 没有数据库, 还没有处理各种异常。
登录:输入用户名点击的登录即可。
发送消息: 特定格式->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;
}
|
希望本文所述对大家学习有所帮助。