Android---51---加入多线程进行Socket通信

前面服务器和客户端只是进行了简单的通信操作:服务器接收到客户端连接之后
服务器向客户端输出一个字符串,而客户端也只是读取服务器的字符串之后就退出了

而实际 应用中的客户端则可能需要和服务器保持长时间的通信,即服务器
需要不断的读取客户端的数据,并向客户端写入数据;客户端也需要不断的
读取服务器,并向数据库中写入数据。


使用传统BufferedReader的 readLine 方法读取数据时,当该方法成功返回之前,该线程
是阻塞的,程序无法继续进行。所以,服务器应该为每一个Socket开启一个线程,每条线程
负责与一个客户端进行通信。


服务器端:

 

class ServerThread implements Runnable {

	Socket s;
	BufferedReader br;

	public ServerThread(Socket s) throws IOException {
		super();
		this.s = s;
		br = new BufferedReader(new InputStreamReader(s.getInputStream()));
	}

	@Override
	public void run() {
		String content = null;
		try {
			while ((content = readFromClient()) != null) {
				for (Socket s : MultiThreadServer.sockets) {
					OutputStream os;
					os = s.getOutputStream();
					os.write((content + "\n").getBytes("utf-8"));
					
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private String readFromClient() {
		try {
			return br.readLine();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

}

public class MultiThreadServer {

	public static ArrayList<Socket> sockets = new ArrayList<Socket>();

	public static void main(String[] args) throws IOException {
		ServerSocket ss = new ServerSocket(45623);
		while (true) {
			Socket s = ss.accept();
			sockets.add(s);
			new Thread(new ServerThread(s)).start();
		}
	}
}


 

每当客户端Socket连接到该ServerSocket之后,
程序将对应Socket加入到集合中保存,并为该Socket开启一条线程,负责处理该Socket的
所有通信事务。


客户端:

 

MultiClient:

 

 

public class MultiThreadClient extends Activity {

	EditText input;
	TextView show;
	Button send;
	Handler handler;
	ClientThread clientThread;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_client_thread);

		input = (EditText) findViewById(R.id.input);
		show = (TextView) findViewById(R.id.show);
		send = (Button) findViewById(R.id.send);

		handler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				// 如果消息来自于子线程
				if (msg.what == 0x123) {
					// 将读取的内容追加显示在文本中
					show.append("\n" + msg.obj.toString());
				}
			}
		};

		clientThread = new ClientThread(handler);
		// 客户端启动ClientThread线程创建网络连接、读取来自服务器的数据
		new Thread(clientThread).start();

		send.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// 当用户按下发送按钮后,将用户输入的数据封装成Message,然后发送给子线程的handler
				Message msg = new Message();
				msg.what = 0x345;
				msg.obj = input.getText().toString();
				clientThread.revHandler.sendMessage(msg);
				input.setText("");
			}
		});
	}
}


 

ClientThread:

 

public class ClientThread implements Runnable {

	private Socket s;
	// 定义向UI线程发送消息的Handler对象。
	private Handler handler;
	// 定义接收UI线程的消息的Handler对象.
	public Handler revHandler;
	// 该线程所处理的Socket所对用的流对象
	BufferedReader br;
	OutputStream os;

	public ClientThread(Handler handler) {
		super();
		this.handler = handler;
	}

	@Override
	public void run() {
		try {
			s = new Socket("192.168.3.12", 45623);
			br = new BufferedReader(new InputStreamReader(s.getInputStream()));
			os = s.getOutputStream();
			// 启动一条子线程
			new Thread() {
				public void run() {
					String content = null;
					// 不断读取Socket输入流中的内容
					try {
						while ((content = br.readLine()) != null) {
							// 每当读到来自服务器的数据之后,发送消息通知程序界面显示该数据
							Message msg = new Message();
							msg.what = 0x123;
							msg.obj = content;
							handler.sendMessage(msg);

						}
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				};
			}.start();

			// 为当前线程初始化Looper
			Looper.prepare();
			// 创建revhandler对象
			revHandler = new Handler() {
				@Override
				public void handleMessage(Message msg) {
					// 接收UI线程中用户输入的数据
					if (msg.what == 0x345) {
						// 将用户在文本框内输入的内容写入网络
						try {
							os.write((msg.obj.toString() + "\r\n").getBytes("utf-8"));
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
			};
			
			Looper.loop();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}










 

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。