Android应用开发提高篇(4)-----Socket编程(多线程、双向通信)

一、概述

      关于Socket编程的基本方法在基础篇里已经讲过,今天把它给完善了。加入了多线程,这样UI线程就不会被阻塞;实现了客户端和服务器的双向通信,只要客户端发起了连接并成功连接后那么两者就可以随意进行通信了。

 

二、实现

     在之前的工程基础上进行修改就可以了。

     MyClient工程的main.xml文件不用修改,只需要修改MyClientActivity.java文件,主要是定义了一个继承自Thread类的用于接收数据的类,覆写了其中的run()方法,在这个函数里面接收数据,接收到数据后就通过Handler发送消息,收到消息后在UI线程里更新接收到的数据。完整的内容如下:

 

package com.nan.client;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.Socket;
 import java.net.UnknownHostException;
 
 import android.app.Activity;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
 import android.view.View;
 import android.widget.Button;
 import android.widget.EditText;
 import android.widget.TextView;
 import android.widget.Toast;
 
 
 public class MyClientActivity extends Activity 
 {
     private EditText mEditText = null;
     private Button connectButton = null;
     private Button sendButton = null;
     private TextView mTextView = null;
     
     private Socket clientSocket = null;
     private OutputStream outStream = null;
     
     private Handler mHandler = null;
     
     private ReceiveThread mReceiveThread = null;
     private boolean stop = true;
     
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState) 
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
         
         mEditText = (EditText)this.findViewById(R.id.edittext);
         mTextView = (TextView)this.findViewById(R.id.retextview);
         connectButton = (Button)this.findViewById(R.id.connectbutton);
         sendButton = (Button)this.findViewById(R.id.sendbutton);
         sendButton.setEnabled(false);      
         
         //连接按钮监听
         connectButton.setOnClickListener(new View.OnClickListener() 
         {
             
             @Override
             public void onClick(View v) 
             {
                 // TODO Auto-generated method stub
                 try 
                 {
                     //实例化对象并连接到服务器
                     clientSocket = new Socket("113.114.170.246",8888);
                 } 
                 catch (UnknownHostException e) 
                 {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 } 
                 catch (IOException e) 
                 {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
                 
                 displayToast("连接成功!");                        
                 //连接按钮使能
                 connectButton.setEnabled(false);
                 //发送按钮使能
                 sendButton.setEnabled(true);
                 
                 mReceiveThread = new ReceiveThread(clientSocket);
                 stop = false;
                 //开启线程
                 mReceiveThread.start();
             }
         });
         
         //发送数据按钮监听
         sendButton.setOnClickListener(new View.OnClickListener() 
         {
             
             @Override
             public void onClick(View v) 
             {
                 // TODO Auto-generated method stub
                 byte[] msgBuffer = null;
                 //获得EditTex的内容
                 String text = mEditText.getText().toString();
                 try {
                     //字符编码转换
                     msgBuffer = text.getBytes("GB2312");
                 } catch (UnsupportedEncodingException e1) {
                     // TODO Auto-generated catch block
                     e1.printStackTrace();
                 }
                             
                 
                 try {
                     //获得Socket的输出流
                     outStream = clientSocket.getOutputStream();
                 } catch (IOException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }                                                    
                 
                 
                 try {
                     //发送数据
                     outStream.write(msgBuffer);
                 } catch (IOException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
                 //清空内容
                 mEditText.setText("");
                 displayToast("发送成功!");
             }
         });
               
         //消息处理
         mHandler = new Handler()
         {
             @Override
             public void handleMessage(Message msg)
             {
                 //显示接收到的内容
                 mTextView.setText((msg.obj).toString());
             }
         };
         
     }
     
     //显示Toast函数
     private void displayToast(String s)
     {
         Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
     }
     
     
     private class ReceiveThread extends Thread
     {
         private InputStream inStream = null;
         
         private byte[] buf;  
         private String str = null;
         
         ReceiveThread(Socket s)
         {
             try {
                 //获得输入流
                 this.inStream = s.getInputStream();
             } catch (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
         }      
         
         @Override
         public void run()
         {
             while(!stop)
             {
                 this.buf = new byte[512];
                 
                 try {
                     //读取输入数据(阻塞)
                     this.inStream.read(this.buf);
                 } catch (IOException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 } 
                 
                 //字符编码转换
                 try {
                     this.str = new String(this.buf, "GB2312").trim();
                 } catch (UnsupportedEncodingException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
                 
                 Message msg = new Message();
                 msg.obj = this.str;
                 //发送消息
                 mHandler.sendMessage(msg);
                 
             }
         }
         
         
     }
     
     @Override
     public void onDestroy()
     {
         super.onDestroy();
         
         if(mReceiveThread != null)
         {
             stop = true;
             mReceiveThread.interrupt();
         }
     }
      
 }

 

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <TextView
        android:id="@+id/retextview"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>

    <EditText
        android:id="@+id/edittext"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:text="连接"
        android:id="@+id/connectbutton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:text="发送"

        android:id="@+id/sendbutton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

 

对于MyServer工程,改动比较大,首先是main.xml文件,在里面添加了两个TextView,一个用于显示客户端的IP,一个用于显示接收到的内容,一个用于发送数据的Button,还有一个EditText,完整的main.xml如下:

 

package com.nan.server;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.ServerSocket;
 import java.net.Socket;
 
 import android.app.Activity;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
 import android.view.View;
 import android.widget.Button;
 import android.widget.EditText;
 import android.widget.TextView;
 import android.widget.Toast;
 
 
 public class MyServerActivity extends Activity 
 {
     private TextView ipTextView = null;
     private EditText mEditText = null;
     private Button sendButton = null;
     private TextView mTextView = null;
     
     private OutputStream outStream = null;
     private Socket clientSocket = null;
     private ServerSocket mServerSocket = null;
     
     private Handler mHandler = null;
     
     private AcceptThread mAcceptThread = null;
     private ReceiveThread mReceiveThread = null;
     private boolean stop = true;
     
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState) 
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
         
         ipTextView = (TextView)this.findViewById(R.id.iptextview);
         mEditText = (EditText)this.findViewById(R.id.sedittext);
         sendButton = (Button)this.findViewById(R.id.sendbutton);
         sendButton.setEnabled(false);
         mTextView = (TextView)this.findViewById(R.id.textview);
         
         //发送数据按钮监听
         sendButton.setOnClickListener(new View.OnClickListener() 
         {
             
             @Override
             public void onClick(View v) 
             {
                 // TODO Auto-generated method stub
                 byte[] msgBuffer = null;
                 //获得EditTex的内容
                 String text = mEditText.getText().toString();
                 try {
                     //字符编码转换
                     msgBuffer = text.getBytes("GB2312");
                 } catch (UnsupportedEncodingException e1) {
                     // TODO Auto-generated catch block
                     e1.printStackTrace();
                 }
                             
                 
                 try {
                     //获得Socket的输出流
                     outStream = clientSocket.getOutputStream();
                 } catch (IOException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }                                                    
                 
                 
                 try {
                     //发送数据
                     outStream.write(msgBuffer);
                 } catch (IOException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
                 //清空内容
                 mEditText.setText("");
                 displayToast("发送成功!");
                 
             }
         });
         //消息处理
         mHandler = new Handler()
         {
             @Override
             public void handleMessage(Message msg)
             {
                 switch(msg.what)
                 {
                     case 0:
                     {
                         //显示客户端IP
                         ipTextView.setText((msg.obj).toString());
                         //使能发送按钮
                         sendButton.setEnabled(true);
                         break;
                     }
                     case 1:
                     {
                         //显示接收到的数据
                         mTextView.setText((msg.obj).toString());
                         break;
                     }                 
                 }                                           
                 
             }
         };
         
         
         mAcceptThread = new AcceptThread();
         //开启监听线程
         mAcceptThread.start();
               
     }
     
     //显示Toast函数
     private void displayToast(String s)
     {
         Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
     }
     
     
     private class AcceptThread extends Thread
     {
         @Override
         public void run()
         {
             try {
                 //实例化ServerSocket对象并设置端口号为8888
                 mServerSocket = new ServerSocket(8888);
             } catch (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
             
             try {
                 //等待客户端的连接(阻塞)
                 clientSocket = mServerSocket.accept();
             } catch (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
             
             mReceiveThread = new ReceiveThread(clientSocket);
             stop = false;
             //开启接收线程
             mReceiveThread.start();
             
             Message msg = new Message();
             msg.what = 0;
             //获取客户端IP
             msg.obj = clientSocket.getInetAddress().getHostAddress();
             //发送消息
             mHandler.sendMessage(msg);
             
         }
         
     }
     
     
     private class ReceiveThread extends Thread
     {
         private InputStream mInputStream = null;
         private byte[] buf ;  
         private String str = null;
         
         ReceiveThread(Socket s)
         {
             try {
                 //获得输入流
                 this.mInputStream = s.getInputStream();
             } catch (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
         }
         
         @Override
         public void run()
         {
             while(!stop)
             {
                 this.buf = new byte[512];
                 
                 //读取输入的数据(阻塞读)
                 try {
                     this.mInputStream.read(buf);
                 } catch (IOException e1) {
                     // TODO Auto-generated catch block
                     e1.printStackTrace();
                 }
                 
                 //字符编码转换
                 try {
                     this.str = new String(this.buf, "GB2312").trim();
                 } catch (UnsupportedEncodingException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
                 
                 Message msg = new Message();
                 msg.what = 1;        
                 msg.obj = this.str;
                 //发送消息
                 mHandler.sendMessage(msg);
                 
             }
         }
     }
     
       
     @Override
     public void onDestroy()
     {
         super.onDestroy();
         
         if(mReceiveThread != null)
         {
             stop = true;
             mReceiveThread.interrupt();
         }
     }
     
     
 }

 

<?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:orientation="vertical" >
 
     <TextView 
         android:id="@+id/iptextview"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:textSize="20dip"
         android:gravity="center_horizontal"
         />
     
     <EditText 
         android:id="@+id/sedittext"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:hint="请输入要发送的内容"
         />
     
     <Button 
         android:id="@+id/sendbutton"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:text="发送"
         />
     
     <TextView
         android:id="@+id/textview"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:textSize="15dip"
          
         />
 
 </LinearLayout>

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值