Androidに基づいて開発されたチャットルームChatRoom 1.0:(二)メッセージ処理メカニズム


本アプリケーションはsocket通信メカニズムに基づいており、クライアントとサーバ側がメッセージのインタラクションを行う際にメッセージに識別行を追加し、メッセージのタイプ(登録、ログイン、終了、文字メッセージ、音声メッセージ)を識別し、異なるメッセージタイプに応じて異なるデータ処理を行う.一対のマルチチャットであるため、サーバ側ではすべてのオンラインユーザー情報がキャッシュされ、各ユーザーの顔データが含まれている.ここでは、通常のxmlファイルを使用して、データベースとしてユーザの登録情報を保存します.次に、クライアントとサーバ側のメッセージ処理の概略的な流れを列挙します.
 
サーバ側:サーバ側がオンになると、socketリクエストが送信されると、スレッドがリクエストを処理します.まず識別行を読み出し,メッセージのタイプを判断し,メッセージのタイプに応じて異なる処理を行う.同時に、サーバ側ですべてのオープンスレッドがコレクションでキャッシュされるため、1対以上の送信が必要なメッセージに対してそのコレクションがループし、すべてのオンラインクライアントがメッセージを受信できることを保証します.
public class ChatServer {
	private ExecutorService executorService;//    
	private int port;//     
	private boolean quit = false;//   
	private ServerSocket server;
	private List<SocketTask> taskList = new ArrayList<SocketTask>();//        socket  

	public ChatServer(int port) {
		this.port = port;
		//      ,    (cpu  *50)   
		executorService = Executors.newFixedThreadPool(Runtime.getRuntime()
				.availableProcessors() * 50);
	}

	/**
	 *      ,      
	 */
	public void quit() {
		this.quit = true;
		try {
			for (SocketTask tast : taskList) {
				tast.input.close();
			}
			server.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 *      
	 * 
	 * @throws Exception
	 */
	public void start() throws Exception {
		server = new ServerSocket(port);
		new Thread(new Runnable() {
			public void run() {
				while (!quit) {
					try {
						System.out.println("     socket  ");
						Socket socket = server.accept();
						//           ,                 
						SocketTask newTask = new SocketTask(socket);
						taskList.add(newTask);
						executorService.execute(newTask);
						System.out.println("          socket  ");
					} catch (Exception e) {
						System.out.println("     !      ");
					}
				}
			}
		}).start();
	}

	/**
	 *      ,             
	 * 
	 * @author Administrator
	 */
	private final class SocketTask implements Runnable {
		private Socket s;
		private DataInputStream input;
		private DataOutputStream output;
		private User curUser;

		public SocketTask(Socket socket) {
			s = socket;
			try {
				input = new DataInputStream(s.getInputStream());
				output = new DataOutputStream(s.getOutputStream());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		/**
		 *     
		 * 
		 * @param msg
		 * @param datas
		 */
		public void sendMsg(String msg, byte[] datas) {
			try {
				if (null != msg) {
					output.writeUTF(msg);
				}
				if (null != datas) {
					output.writeInt(datas.length);
					output.write(datas, 0, datas.length);
				}
				output.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void run() {
			try {
				while (true) {
					String msgCtn = input.readUTF();
					if (msgCtn.startsWith(ContentFlag.REGOSTER_FLAG)) { //       
						String name = msgCtn.substring(
								ContentFlag.REGOSTER_FLAG.length()).trim();
						String userId = XmlParser.saveUserInfo(name, input);
						System.out.println("     id" + userId);
						this.sendMsg(userId, null);
						taskList.remove(this);
						break;
					} else if (msgCtn.startsWith(ContentFlag.ONLINE_FLAG)) { //       
						//          
						String loginId = msgCtn.substring(
								ContentFlag.ONLINE_FLAG.length()).trim();
						System.out.println("       ID:" + loginId);
						curUser = XmlParser.queryUserById(Integer
								.parseInt(loginId));
						//                             
						int imgNums = taskList.size() - 1; //      
						System.out.println("       :" + taskList.size());
						this.output.writeInt(imgNums);
						if (imgNums > 0) {
							for (SocketTask task : taskList) {
								if (task != this) {
									long userId = task.curUser.getId();
									File img = new File("image\\"
											+ XmlParser.queryUserById(userId)
													.getImg());
									FileInputStream flleInput = new FileInputStream(
											img);
									byte data[] = StreamTool
											.readStream(flleInput);
									this.sendMsg(String.valueOf(userId), data);
								}
							}
						}
						//         
						File imgFile = new File("image\\" + curUser.getImg());
						FileInputStream flleInput = new FileInputStream(imgFile);
						byte datas[] = StreamTool.readStream(flleInput);
						String send_person = curUser.getName(); //    
						String send_ctn = "     !"; //     
						String send_date = FormatDate.getCurDate(); //     
						StringBuilder json = new StringBuilder();
						json.append("[{");
						json.append("id:").append(loginId)
								.append(",send_person:\"").append(send_person)
								.append("\",send_ctn:\"").append(send_ctn)
								.append("\",send_date:\"").append(send_date);
						json.append("\"}]");
						System.out.println("json:" + json);
						//         Socket         
						for (SocketTask tast : taskList) {
							System.out.println("          ");
							tast.sendMsg(
									ContentFlag.ONLINE_FLAG
											+ this.curUser.getId(), null);
							tast.sendMsg(json.toString(), datas);
						}
						flleInput.close();
					} else if (msgCtn.startsWith(ContentFlag.OFFLINE_FLAG)) { //       
						taskList.remove(this);
						//        ID
						String id = msgCtn.substring(
								ContentFlag.OFFLINE_FLAG.length()).trim();
						StringBuilder json = new StringBuilder();
						json.append("[{");
						json.append("id:").append(this.curUser.getId())
								.append(",send_person:\"")
								.append(this.curUser.getName())
								.append("\",send_ctn:\"").append("     !")
								.append("\",send_date:\"")
								.append(FormatDate.getCurDate());
						json.append("\"}]");
						for (SocketTask tast : taskList) {
							if (tast != this) {
								tast.sendMsg(ContentFlag.OFFLINE_FLAG + id,
										null);
								tast.sendMsg(json.toString(), null);
							}
						}
						System.out.println("  " + curUser.getName() + "  !,    "
										+ Thread.currentThread().getName());
						break;
					} else if (msgCtn.startsWith(ContentFlag.RECORD_FLAG)) { //       
						String filename = msgCtn
								.substring(ContentFlag.RECORD_FLAG.length());
						long recordTime = input.readLong();
						byte datas[] = StreamTool.readStream(input);
						StringBuilder json = new StringBuilder();
						json.append("[{");
						json.append("id:").append(this.curUser.getId())
								.append(",send_person:\"")
								.append(this.curUser.getName())
								.append("\",send_ctn:\"")
								.append(recordTime / 1000 + "\'")
								.append("\",send_date:\"")
								.append(FormatDate.getCurDate())
								.append("\",recordTime:\"").append(recordTime);
						json.append("\"}]");
						System.out.println("json:" + json);
						//         Socket       
						for (SocketTask tast : taskList) {
							tast.sendMsg(ContentFlag.RECORD_FLAG + filename,
									null);
							tast.sendMsg(json.toString(), datas);
						}
					} else { //       
						StringBuilder json = new StringBuilder();
						json.append("[{");
						json.append("id:").append(this.curUser.getId())
								.append(",send_person:\"")
								.append(this.curUser.getName())
								.append("\",send_ctn:\"").append(msgCtn)
								.append("\",send_date:\"")
								.append(FormatDate.getCurDate());
						json.append("\"}]");
						for (SocketTask tast : taskList) {
							tast.sendMsg(json.toString(), null);
						}
					}
				}
			} catch (Exception e) {
				taskList.remove(this);
				System.out.println("    " + Thread.currentThread().getName());
			} finally {
				try {
					if (null != input)
						input.close();
					if (null != output)
						output.close();
					if (null != s)
						s.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

クライアント:socket接続が確立されると、メッセージを待つ処理が開始され、サーバ側と同様に、まずデータ行を読み出し、メッセージタイプを判断し、異なるタイプに応じて異なるデータ処理を行う.
public void receiveMsg(IhandleMessge handle) throws IOException {
		try {
			while(true){
				String msgCtn = input.readUTF();
				if(msgCtn.startsWith(ContentFlag.ONLINE_FLAG)){				//      
					String json = input.readUTF();
					Message msg = parseJsonToObject(json);
					byte[] datas = StreamTool.readStream(input);
				    Bitmap bitmap = BitmapFactory.decodeByteArray(datas, 0, datas.length);
					msg.setBitmap(bitmap);
					handle.handleMsg(msg);
					imgMap.put(msg.getId(), bitmap);
				}else if(msgCtn.startsWith(ContentFlag.OFFLINE_FLAG)){		//      
					String json = input.readUTF();
					Message msg = parseJsonToObject(json);
					msg.setBitmap(imgMap.get(msg.getId()));
					handle.handleMsg(msg);
					imgMap.remove(msg.getId());
				}else if(msgCtn.startsWith(ContentFlag.RECORD_FLAG)){		//      
					String filename = msgCtn.substring(ContentFlag.RECORD_FLAG.length());
					File dir = new File(Environment.getExternalStorageDirectory() + "/recordMsg/");
					if(!dir.exists()) dir.mkdirs();
					File file = new File(dir, filename);
					String json = input.readUTF();
					Message msg = parseJsonToObject(json);
					msg.setRecord_path(file.getAbsolutePath());
					msg.setBitmap(imgMap.get(msg.getId()));
					msg.setIfyuyin(true);
					handle.handleMsg(msg);
					saveRecordFile(file);
				}else{														//      
					Message msg = parseJsonToObject(msgCtn);
					msg.setBitmap(imgMap.get(msg.getId()));
					handle.handleMsg(msg);
				}
			}
		} catch (Exception e) {
			if (!socket.isClosed()) {
				throw new IOException("fail connect to the server");
			}
		}
	}

完全なリソースコードのダウンロードアドレス:http://download.csdn.net/detail/jiangliloveyou/6457969