項目位址:https://github.com/SunnyLine/ChatRoom.git
切換“test”分支,運作old_server,安裝app到手機上
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL6VEROlXR6hld4dkYshmMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL1kTN1UDM0EjM4IjMxkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
部分截圖:
以下為代碼邏輯部分
Java: 監聽某個端口,有使用者通路時,将這個Socket放入到一個集合中作為一個使用者組,并監聽這個Socket的消息。收到任意一個Socket的消息後,再将此消息分發給使用者組的每一個成員。
Android:使用Socket連接配接指定IP指定端口,連接配接成功後發送一條資訊給伺服器,伺服器會将之轉發給其他人,其他人就可以知道組内有新使用者加入的資訊。離開此頁面時也要發送給伺服器一條離開的資訊,伺服器會告知其他使用者。在子線程中監聽伺服器發送的資料進行顯示。
Java代碼如下:
public class Main {
private static final int PORT = 9999;
private static List<Socket> mList = new ArrayList<Socket>();
private static ServerSocket server = null;
private static ExecutorService mExecutorService = null; //thread pool
public static void main(String[] args) {
try {
server = new ServerSocket(PORT);
mExecutorService = Executors.newCachedThreadPool(); //create a thread pool
System.out.println("伺服器已啟動...");
Socket client = null;
while(true) {
client = server.accept();
//把用戶端放入用戶端集合中
mList.add(client);
mExecutorService.execute(new Service(client)); //start a new thread to handle the connection
}
}catch (Exception e) {
e.printStackTrace();
}
}
static class Service implements Runnable {
private Socket socket;
private BufferedReader in = null;
private String msg = "";
public Service(Socket socket) {
this.socket = socket;
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//用戶端隻要一連到伺服器,便向用戶端發送下面的資訊。
} catch (IOException e) {
e.printStackTrace();
}
}
public byte[] readStream(InputStream inStream) throws Exception {
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
outSteam.close();
inStream.close();
return outSteam.toByteArray();
}
@Override
public void run() {
try {
while(true) {
if((msg = in.readLine())!= null) {
System.out.println("接收:"+msg);
ChatBean bean = new Gson().fromJson(msg, ChatBean.class);
//當用戶端發送的資訊為:exit時,關閉連接配接
if(bean.content.equals("exit")) {
System.out.println("用戶:"+bean.name+"已退出談論組");
mList.remove(socket);
in.close();
socket.close();
this.sendmsg();
break;
//接收用戶端發過來的資訊msg,然後發送給用戶端。
} else {
this.sendmsg();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 循環周遊用戶端集合,給每個用戶端都發送資訊。
* 可以使用觀察者模式設計讨論組
*/
public void sendmsg() {
System.out.println(msg);
int num =mList.size();
for (int index = 0; index < num; index ++) {
Socket mSocket = mList.get(index);
PrintWriter pout = null;
try {
pout = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(mSocket.getOutputStream())),true);
pout.println(msg);
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Android 部分代碼如下:
public interface ChatView {
public String getHost();
public String getProt();
public String getUserId();
public void showDiaolg(String msg);
public void receiveMsg(ChatBean bean);
}
public class SocketThread extends Thread {
private Socket socket = null;
private BufferedReader in = null;
private PrintWriter out = null;
private ChatView chatView;
public SocketThread(ChatView chatView) {
this.chatView = chatView;
}
private void init() {
try {
socket = new Socket(chatView.getHost(), Integer.parseInt(chatView.getProt()));
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
if (!socket.isOutputShutdown()) {
ChatBean bean = new ChatBean("join", chatView.getUserId());
out.println(new Gson().toJson(bean));
}
} catch (UnknownHostException e1) {
e1.printStackTrace();
mHandler.sendEmptyMessage(-1);
} catch (IOException ex) {
ex.printStackTrace();
mHandler.sendEmptyMessage(0);
} catch (IllegalArgumentException e2) {
e2.printStackTrace();
mHandler.sendEmptyMessage(-2);
}
}
public void sendMsg(String msg) {
ChatBean bean = new ChatBean(msg, chatView.getUserId());
if (!TextUtils.isEmpty(msg) && socket != null && socket.isConnected()) {
if (!socket.isOutputShutdown()) {
out.println(new Gson().toJson(bean));
}
}
}
//接收線程發送過來資訊,并用TextView顯示
public Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case -2:
chatView.showDiaolg("IllegalArgumentException");
break;
case -1:
chatView.showDiaolg("UnknownHostException");
break;
case 0:
chatView.showDiaolg("IOException");
break;
case 1:
String content = (String) msg.obj;
ChatBean bean = new Gson().fromJson(content, ChatBean.class);
chatView.receiveMsg(bean);
break;
}
}
};
@Override
public void run() {
super.run();
init();
//接收伺服器的資訊
try {
while (true) {
if (!socket.isClosed()) {
if (socket.isConnected()) {
if (!socket.isInputShutdown()) {
String content;
if ((content = in.readLine()) != null) {
content += "\n";
Message message = mHandler.obtainMessage();
message.obj = content;
message.what = 1;
mHandler.sendMessage(message);
} else {
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}