Android开发:Socket通信

来源:互联网 发布:竹纤维毛巾知乎 编辑:程序博客网 时间:2024/05/20 01:36
使用Socket时遇到诸多问题,略做记录以备后时之需:
1.最初于《疯狂Android讲义》(2011年7月第一次印刷)中找到了Socket的相关介绍,然由于Android版本更新(暂且认为是4.0之后,待考)的缘故,书中代码于真机已不再适用logcat中记录错误android.os.NetworkOnMainThreadException,在http://stackoverflow.com/questions/6343166/android-os-networkonmainthreadexception中找到解释,“Thisexception is thrown when an application attempts to perform anetworking operation on its main thread.Run your code inAsyncTask”,就是说新版本的Android中已不再允许应用于主线程(UI线程)中进行网络连接并建议将网络连接放在AsyncTask对象中进行。实践证明后,此方法确实可行,具体代码如下:
//---------------------------------------------------------------------------------------
publicclassPutMsgTask extendsAsyncTask<String, Integer, String>{
   publicvoidrun() {       
   }
   @Override
   protectedString doInBackground(String... arg0) {
      try{
         Socketsocket=new Socket(InetAddress.getByName("192.168.137.1"), 30000);
         socket.setSoTimeout(5000);
          
         OutputStreamos=socket.getOutputStream();
         os.write(arg0[0].getBytes("utf-8"));   
         os.close();
          
         returnarg0[0];
      }
      catch(Exceptione){
         e.printStackTrace();
      }
      return"Error";
   }
   protectedvoidonPostExecute(Stringresult){
      view.append(result+"\n");
      super.onPostExecute(result);
   }
}
//--------------------------------------------------------------------------------------
UI线程中开启AsyncTask的代码:
//--------------------------------------------------------------------------------------
PutMsgTask postTask=new PutMsgTask();
postTask.execute("HenryTank");
//--------------------------------------------------------------------------------------
现记录一些关于AsyncTask的介绍:
Android中使用子线程通过Handler通知主线程更新UI,但太多的子线程给系统带来较大负担。工具类AsyncTask提供异步执行任务功能,AsyncTask生来就是处理一些后台的比较耗时的任务,改善用户体验。
一、参数
AsyncTask是抽象类.AsyncTask定义了三种泛型类型Params,Progress和Result(对应其定义时的AsyncTask <String,Integer,String>,这是本人例子中的定义,Params为String类型,相应的Progress为Integer类型,Result为String类型)。
① Params 启动任务执行的输入参数,比如HTTP请求的URL;② Progress 后台任务执行的百分比;③ Result后台执行任务最终返回的结果,比如String。
二、方法
AsyncTask中主要有四个方法我们可以进行重载,如下:
① onPreExecute(), 该方法将在执行前被UI线程调用,做一些准备工作。②doInBackground(Params...), 将在onPreExecute方法执行后马上执行,该方法运行在后台线程中。主要负责执行那些很耗时的后台计算工作。可以调用publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。③onProgressUpdate(Progress...),在publishProgress方法被调用后,UIthread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。④ onPostExecute(Result),在doInBackground 执行完成后,onPostExecute方法将被UI线程调用,后台的计算结果将通过该方法传递到UI线程.
三、注意事项
①  Task的实例必须在UI线程中创建 ② execute方法必须在UI线程中调用 ③不要手动的调用onPreExecute(),onPostExecute(Result),doInBackground(Params...),onProgressUpdate(Progress...) ④该task只能被执行一次,否则多次调用时将会出现异常,特别不能在doInBackground中引入死循环,这是一种为快速单次执行设计的类型(切记:产生的BUG曾耗费数小时调试,惨痛)


2.测试时无法完成通信,logcat记录为java.net.SocketException: socket failed:EACCES (Permissiondenied),原因是未开启Android的网络通讯全选,添加方法为在AndroidManifest.xml中添加   <uses-permissionandroid:name="android.permission.INTERNET"/>
具体位置如下:
//------------------------------------------------------------------------------------
<uses-sdk
   android:minSdkVersion="8"
   android:targetSdkVersion="16"/>
<uses-permissionandroid:name="android.permission.INTERNET"/>
//------------------------------------------------------------------------------------

3.记录Socket的部分代码如下:
Client:
//------------------------------------------------------------------------------------
Socket socket=new Socket(InetAddress.getByName("192.168.137.1"), 30000);//设置地址、端口号
socket.setSoTimeout(5000);//设置连接最大等待时间,这里超过5秒变抛出错误

OutputStream os=socket.getOutputStream();//获取输出流
os.write("QQ".getBytes("utf-8"));//输出信息QQ  
os.close();//关闭输出流,这里socket也同时关闭
//------------------------------------------------------------------------------------
Server:
//------------------------------------------------------------------------------------
ServerSocket serverSocket = new ServerSocket(30000);//serverSocket在TCP3000端口监听
Socket socket=serverSocket.accept();//获取连接,程序阻塞
//获取输入流
BufferedReaderbr=new BufferedReader(new InputStreamReader(socket.getInputStream()));          
//读取socket传递的信息
if(br.readLine().contentEquals("Accept:QQ")){
   System.out.println("Accept Information fromCellphone!");
}
socket.close();//关闭套接字
serverSocket.close();//关闭服务套接字
//------------------------------------------------------------------------------------
0 0