Android Socket编程实例

Android Socket编程实例

http://blog.csdn.net/zfyseu1/article/details/48831219?ref=myread

最近一段时间在断断续续地学习Android应用开发的一些知识,许多APP运行时都要服务器进行通信,socket可以很好完成这样一个功能。我在网上找到了一些手机和服务器通过socket通信的例子,然后挑了其中两个进行整合,供给像我一样的Android socket初学者进行参考。

两个例子的链接:

例子一:http://blog.csdn.net/wuchuanpingstone/article/details/6617276

例子二:http://blog.csdn.net/x605940745/article/details/17001641

我把两个例子整合成以下内容:


一、Android socket使用时要注意的地方

1、在Android主线程中不能有访问socket的操作,否则会报异常。

2、在Android工程配置文件中要进行网络权限声明: <uses-permission   android:name="android.permission.INTERNET"/>

      3、对数据进行发送接收操作时,首先获取socket流,然后可以封装成BufferedWriter和BufferedReader:

[java]  view plain copy
  1. br = new BufferedReader(new InputStreamReader(s.getInputStream()));//把socket输入流封装成BufferedReader  
[java]  view plain copy
  1. os=new PrintWriter(new BufferedWriter(new OutputStreamWriter(s.getOutputStream())), true);//把socket输出流封装成PrintWriter  
[java]  view plain copy
  1. <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">4、对socket进行读写之前还要判断,连接是否还存在:</span>  
[java]  view plain copy
  1. if(!s.isClosed()&&s.isConnected()){  
[java]  view plain copy
  1. //进行socket读写操作<span style="white-space:pre">                                
[java]  view plain copy
  1. }  
     

5、由于在主线程中不能访问网络的操作,所以socket通信还涉及到多线程的知识点;同样,UI控件的更新只能在主线程中进行,所以还涉及到Android消息处理机制相关知识点。


二、实例代码

Android客户端代码:

AndroidManifest.xml配置文件:

[java]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.example.client"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-permission     
  8.     android:name="android.permission.INTERNET"/>   
  9.       
  10.     <uses-sdk  
  11.         android:minSdkVersion="14"  
  12.         android:targetSdkVersion="21" />  
  13.   
  14.     <application  
  15.         android:allowBackup="true"  
  16.         android:icon="@drawable/ic_launcher"  
  17.         android:label="@string/app_name"  
  18.         android:theme="@style/AppTheme" >  
  19.         <activity  
  20.             android:name=".MainActivity"  
  21.             android:label="@string/app_name" >  
  22.             <intent-filter>  
  23.                 <action android:name="android.intent.action.MAIN" />  
  24.   
  25.                 <category android:name="android.intent.category.LAUNCHER" />  
  26.             </intent-filter>  
  27.         </activity>  
  28.     </application>  
  29.   
  30. </manifest>  


activity_main:

[java]  view plain copy
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:layout_width="match_parent"  
  3.     android:layout_height="match_parent"  
  4.     android:orientation="vertical"  
  5.    >  
  6.   
  7.    <EditText    
  8.         android:id="@+id/input"    
  9.         android:layout_width="match_parent"    
  10.         android:layout_height="wrap_content"    
  11.         android:hint="to send to the server" />    
  12.     <Button     
  13.         android:id="@+id/send"    
  14.         android:layout_width="match_parent"    
  15.         android:layout_height="wrap_content"    
  16.         android:text="send"    
  17.         android:layout_below="@id/input"/>    
  18.     <TextView     
  19.         android:id="@+id/show"    
  20.         android:layout_width="match_parent"    
  21.         android:layout_height="wrap_content"    
  22.         android:layout_below="@id/send"/>  
  23.       
  24.       
  25.       
  26.   
  27. </LinearLayout>  



MainActivity.java:

[java]  view plain copy
  1. package com.example.client;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.os.Handler;  
  6. import android.os.Message;  
  7. import android.view.Menu;  
  8. import android.view.MenuItem;  
  9. import android.view.View;  
  10. import android.view.View.OnClickListener;  
  11. import android.widget.Button;  
  12. import android.widget.EditText;  
  13. import android.widget.TextView;  
  14.   
  15.   
  16. public class MainActivity extends Activity {  
  17.   
  18.     // 定义界面上的两个文本框    
  19.     EditText input;    
  20.     TextView show;    
  21.     // 定义界面上的一个按钮    
  22.     Button send;    
  23.     Handler handler;    
  24.     // 定义与服务器通信的子线程    
  25.     ClientThread clientThread;   
  26.       
  27.       
  28.     @Override  
  29.     protected void onCreate(Bundle savedInstanceState) {  
  30.         super.onCreate(savedInstanceState);  
  31.         setContentView(R.layout.activity_main);  
  32.           
  33.         input = (EditText) findViewById(R.id.input);    
  34.         show = (TextView) findViewById(R.id.show);    
  35.         send = (Button) findViewById(R.id.send);    
  36.           
  37.           
  38.         handler = new Handler() {    
  39.     
  40.             @Override    
  41.             public void handleMessage(Message msg) {    
  42.                 // 如果消息来自子线程    
  43.                 if (msg.what == 0x123) {    
  44.                     // 将读取的内容追加显示在文本框中    
  45.                     show.append("\n" + msg.obj.toString());    
  46.                 }    
  47.             }    
  48.         };    
  49.           
  50.         clientThread = new ClientThread(handler);    
  51.         // 客户端启动ClientThread线程创建网络连接、读取来自服务器的数据    
  52.         new Thread(clientThread).start();    
  53.           
  54.           
  55.         send.setOnClickListener(new OnClickListener() {    
  56.     
  57.             @Override    
  58.             public void onClick(View v) {    
  59.                 try {    
  60.                     // 当用户按下按钮之后,将用户输入的数据封装成Message    
  61.                     // 然后发送给子线程Handler    
  62.                     Message msg = new Message();    
  63.                     msg.what = 0x345;    
  64.                     msg.obj = input.getText().toString();    
  65.                     clientThread.revHandler.sendMessage(msg);    
  66.                     input.setText("");    
  67.     
  68.                 } catch (Exception e) {    
  69.     
  70.                 }    
  71.             }    
  72.         });    
  73.           
  74.           
  75.     }  
  76.   
  77.   
  78.        
  79.       
  80.     @Override  
  81.     public boolean onCreateOptionsMenu(Menu menu) {  
  82.         // Inflate the menu; this adds items to the action bar if it is present.  
  83.         getMenuInflater().inflate(R.menu.main, menu);  
  84.         return true;  
  85.     }  
  86.   
  87.     @Override  
  88.     public boolean onOptionsItemSelected(MenuItem item) {  
  89.         // Handle action bar item clicks here. The action bar will  
  90.         // automatically handle clicks on the Home/Up button, so long  
  91.         // as you specify a parent activity in AndroidManifest.xml.  
  92.         int id = item.getItemId();  
  93.         if (id == R.id.action_settings) {  
  94.             return true;  
  95.         }  
  96.         return super.onOptionsItemSelected(item);  
  97.     }  
  98. }  

ClientThread.java:

[java]  view plain copy
  1. package com.example.client;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.BufferedWriter;  
  5. import java.io.IOException;  
  6. import java.io.InputStreamReader;  
  7. import java.io.OutputStream;  
  8. import java.io.OutputStreamWriter;  
  9. import java.io.PrintWriter;  
  10. import java.net.InetSocketAddress;  
  11. import java.net.Socket;  
  12. import java.net.SocketTimeoutException;  
  13.   
  14. import android.os.Handler;  
  15. import android.os.Looper;  
  16. import android.os.Message;  
  17.   
  18. public class ClientThread implements Runnable {  
  19.   
  20.     private Socket s;    
  21.     // 定义向UI线程发送消息的Handler对象    
  22.     Handler handler;    
  23.     // 定义接收UI线程的Handler对象    
  24.     Handler revHandler;    
  25.     // 该线程处理Socket所对用的输入输出流    
  26.     BufferedReader br = null;    
  27.     //OutputStream os = null;  
  28.     PrintWriter os = null;  
  29.       
  30.     public ClientThread(Handler handler) {    
  31.         this.handler = handler;    
  32.     }    
  33.   
  34.     @Override    
  35.     public void run() {  //接收数据线程是发送数据线程的子线程  
  36.         s = new Socket();    
  37.         try {    
  38.             s.connect(new InetSocketAddress("121.248.52.236"3000), 5000);    
  39.             br = new BufferedReader(new InputStreamReader(s.getInputStream()));    
  40.            // os = s.getOutputStream();   
  41.             os=new PrintWriter(new BufferedWriter(new OutputStreamWriter(s.getOutputStream())), true);  
  42.             // 启动一条子线程来读取服务器相应的数据    
  43.             new Thread(new Runnable() {    
  44.     
  45.                 @Override    
  46.                 public void run() {    
  47.                     String content = null;    
  48.                     // 不断的读取Socket输入流的内容    
  49.                     try {    
  50.                         while ((content = br.readLine()) != null) {    
  51.                             // 每当读取到来自服务器的数据之后,发送的消息通知程序    
  52.                             // 界面显示该数据    
  53.                             if(!s.isClosed()&&s.isConnected()){  
  54.                                 Message msg = new Message();    
  55.                                 msg.what = 0x123;    
  56.                                 msg.obj = content;    
  57.                                 handler.sendMessage(msg);    
  58.                             }  
  59.                         }    
  60.                     } catch (IOException io) {    
  61.                         io.printStackTrace();    
  62.                     }    
  63.                 }    
  64.     
  65.             }).start();    
  66.             // 为当前线程初始化Looper    
  67.             Looper.prepare();    
  68.             // 创建revHandler对象    
  69.             revHandler = new Handler() {    
  70.     
  71.                 @Override    
  72.                 public void handleMessage(Message msg) {    
  73.                     // 接收到UI线程的中用户输入的数据    
  74.                     if (msg.what == 0x345) {    
  75.                         // 将用户在文本框输入的内容写入网络    
  76.                         try {   
  77.                             if(!s.isClosed()&&s.isConnected()){  
  78.                                 //os.write((msg.obj.toString() + "\r\n").getBytes("gbk"));    
  79.                                 os.println(msg.obj.toString());  
  80.                             }  
  81.                         } catch (Exception e) {    
  82.                             e.printStackTrace();    
  83.                         }    
  84.                     }  
  85.                       
  86.                       
  87.                 }    
  88.     
  89.             };     
  90.             // 启动Looper    
  91.             Looper.loop();    
  92.     
  93.         } catch (SocketTimeoutException e) {    
  94.             Message msg = new Message();    
  95.             msg.what = 0x123;    
  96.             msg.obj = "网络连接超时!";    
  97.             handler.sendMessage(msg);    
  98.         } catch (IOException io) {    
  99.             io.printStackTrace();    
  100.         }    
  101.     
  102.     }    
  103.   
  104.       
  105.   
  106. }  

Java服务端代码:


MyService.java:

[java]  view plain copy
  1. package com.android.net;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.ServerSocket;  
  5. import java.net.Socket;  
  6. import java.util.ArrayList;  
  7. import java.util.List;  
  8.   
  9. public class MyService {  
  10.   
  11.     // 定义保存所有的Socket    
  12.     public static List<Socket> socketList = new ArrayList<Socket>();    
  13.     
  14.     public static void main(String[] args) throws IOException {    
  15.         System.out.println("Server start...");  
  16.         ServerSocket server = new ServerSocket(3000);    
  17.         while(true){    
  18.             Socket s=server.accept();    
  19.             socketList.add(s);    
  20.             //每当客户端连接之后启动一条ServerThread线程为该客户端服务    
  21.             new Thread(new ServiceThreada(s)).start();    
  22.                 
  23.         }    
  24.     }    
  25.   
  26. }  


ServiceThreada.java:

[java]  view plain copy
  1. package com.android.net;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.BufferedWriter;  
  5. import java.io.IOException;  
  6. import java.io.InputStreamReader;  
  7. import java.io.OutputStream;  
  8. import java.io.OutputStreamWriter;  
  9. import java.io.PrintWriter;  
  10. import java.net.Socket;  
  11.   
  12. public class ServiceThreada implements Runnable {  
  13.   
  14.      // 定义当前线程处理的Socket    
  15.     Socket s = null;    
  16.     // 该线程所处理的Socket所对应的输入流    
  17.     BufferedReader br = null;    
  18.     
  19.     public ServiceThreada(Socket s) {    
  20.         this.s = s;    
  21.         try {    
  22.             br = new BufferedReader(new InputStreamReader(s.getInputStream()));    
  23.         } catch (IOException e) {    
  24.             e.printStackTrace();    
  25.         }    
  26.     }    
  27.     
  28.     @Override    
  29.     public void run() {    
  30.     
  31.         String content = null;    
  32.         //采用循环不断的从Socket中读取客户端发送过来的数据    
  33.         while((content=readFromClient())!=null){    
  34.             //遍历socketList中的每个Socket    
  35.             //将读取到的内容每个向Socket发送一次    
  36.            // for(Socket s:MyService.socketList)    
  37.             if(!s.isClosed()&&s.isConnected()){  
  38.                 //OutputStream os;  
  39.                 PrintWriter os=null;  
  40.                 try {  
  41.                      //os = s.getOutputStream();   
  42.                     os=new PrintWriter(new BufferedWriter(new OutputStreamWriter(    
  43.                             s.getOutputStream())), true);  
  44.                     if(content.equals("quit")){  
  45.                         System.out.println("user"+s.getInetAddress()+"offline");  
  46.                         //os.write(("From server:"+"user"+s.getInetAddress()+"offline"+"\n").getBytes("gbk"));  
  47.                         os.println("From server:user:"+s.getInetAddress()+"offline");  
  48.                         s.close();  
  49.                     }else{  
  50.                         System.out.println("From client:"+content);  
  51.                         //os.write(("From server:"+content+"\n").getBytes("gbk"));  
  52.                         os.println("From server:"+content);  
  53.                     }  
  54.                 } catch (IOException e) {    
  55.                     // TODO Auto-generated catch block    
  56.                     e.printStackTrace();    
  57.                 }    
  58.                     
  59.             }    
  60.         }    
  61.     
  62.     }    
  63.     
  64.     // 定义读取客户端的信息    
  65.     public String readFromClient() {    
  66.         try {    
  67.             if(!s.isClosed()&&s.isConnected()){  
  68.                 return br.readLine();    
  69.             }  
  70.         } catch (Exception e) {    
  71.             e.printStackTrace();    
  72.         }    
  73.         return null;    
  74.     }    
  75.       
  76.   
  77. }  


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值