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

来源:互联网 发布:java编程手册 pdf 编辑:程序博客网 时间:2024/05/07 18:15

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

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


使用传统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()));}@Overridepublic 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 blocke.printStackTrace();}}private String readFromClient() {try {return br.readLine();} catch (IOException e) {// TODO Auto-generated catch blocke.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;@Overrideprotected 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() {@Overridepublic 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() {@Overridepublic void onClick(View v) {// 当用户按下发送按钮后,将用户输入的数据封装成Message,然后发送给子线程的handlerMessage 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;}@Overridepublic 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 blocke.printStackTrace();}};}.start();// 为当前线程初始化LooperLooper.prepare();// 创建revhandler对象revHandler = new Handler() {@Overridepublic 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 blocke.printStackTrace();}}}};Looper.loop();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}


 

 

0 0
原创粉丝点击