Android网络编程实践之旅(二):基于Socket的网络通信 .

http://blog.csdn.net/harry_helei/article/details/6638876

Socket(套接字)是一种通信机制,可以实现单机或跨网络进行通信,其创建需要明确的区分C(客户端)/S(服务器端),支持多个客户端连接到同一个服务器。有两种传输模式:

1)、面向连接的传输:基于TCP协议,可靠性高,但效率低;

2)、面向无连接的传输:基于UDP协议,可靠性低,但效率高;

        Android中,直接采用Socket通信应该是我们遇到的最低级的网络运用。尽管已经作了很大程度的抽象,但是纯粹的Socket通信,仍然给开发者留下很多细节需要处理,尤其在服务器端,开发者需要处理多线程以及数据缓冲等的设计问题。相对而言,处于更高抽象层的HTTP等,已经对Socket通信中需要处理的技术细节进行了很好的封装,开发者无须关心,因此,HTTP在网络开发中通常具有决定性的优势。

        Android在其核心库的java包中,提供了用于客户端的Socket class和用于服务器端的ServerSocket class,分别位于$SOURCE/libcore/luni/src/main/java/java/net/Socket.java和$SOURCE/libcore/luni/src/main/java/java/net/ServerSocket.java文件中。分析两个class的源码,可以看出封装考虑的很全面,只构造方法一向每个class都考虑了很多种使用情况。由于本人只是初学者,很多理解的不深入,这里只抛砖引玉的对两个class的构造方法分别介绍一种,就是我下面的程序中用到的:

Socket(String dstName, int dstPort):创建一个以流的方式(基于TCP协议)连接到目标机(这里可以理解为服务器)的客户端Socket;dstName是目标机的IP地址,dstPort是要连接的目标机的端  口号。这里要注意对端口的理解,它不能理解为物理上的一个接口,而是对计算机中一块特殊内存区域的形象表述。

ServerSocket(int aport):创建一个绑定到本机指定端口的服务端Socket;aport就是指定的本机端口。与上述客户端Socket对应,通过TCP连接时,ServerSocket创建后需要在aport端口上进行监听,等待客户端的连接。

        上面所写都是些背景知识,下面对本人的编程实践进行详细说明。

1、功能描述

     1)、简单的基于Socket的数据通信;

     2)、采用TCP方式连接;

     3)、采用C/S结构,但服务端只支持一个连接;

     4)、客户端能够向服务端发送数据,并显示服务端的返回信息;

     5)、服务端能够接收客户端的数据,并将收到的数据以特定的方式返回给客户端;

2、程序实现思路

    1)、服务端:设计为在后台执行的service,用一个独立的线程来处理客户端的连接请求、数据接收和返回。为了启动该service,编写个简单的Activity。

    2)、客户端:设计为一个Activity,界面由三部分组成:显示服务端返回信息的文本区域(一个文本框);进行数据输入的编辑区域(一个编辑框);以及触发连接请求并执行数据发送的触发区域(一个按钮)。

3、服务端源程序

    1)、Activity文件SocketServerDemo.java

  1. package com.android.sample.SocketServerDemo;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.os.Bundle;  
  6.   
  7. public class SocketServerDemo extends Activity{  
  8.   
  9.     @Override  
  10.     protected void onCreate(Bundle savedInstanceState) {  
  11.         // TODO Auto-generated method stub   
  12.         super.onCreate(savedInstanceState);  
  13.           
  14.         setContentView(R.layout.main);  
  15.           
  16.         System.out.println("begin start service");   
  17.         this.startService(new Intent(this, SocketService.class));  
  18.     }  
  19.   
  20.     @Override  
  21.     protected void onDestroy() {  
  22.         // TODO Auto-generated method stub   
  23.         super.onDestroy();  
  24.           
  25.         this.stopService(new Intent(this, SocketService.class));  
  26.     }  
  27. }  
package com.android.sample.SocketServerDemo;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

public class SocketServerDemo extends Activity{

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.main);
		
		System.out.println("begin start service"); 
		this.startService(new Intent(this, SocketService.class));
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		
		this.stopService(new Intent(this, SocketService.class));
	}
}

    2)、service文件SocketService.java

  1. package com.android.sample.SocketServerDemo;  
  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.OutputStreamWriter;  
  8. import java.io.PrintWriter;  
  9. import java.net.ServerSocket;  
  10. import java.net.Socket;  
  11.   
  12. import android.app.Service;  
  13. import android.content.Intent;  
  14. import android.os.IBinder;  
  15.   
  16. public class SocketService extends Service{  
  17.     Thread mServiceThread;  
  18.       
  19.     Socket client;  
  20.       
  21.     @Override  
  22.     public IBinder onBind(Intent intent) {  
  23.         // TODO Auto-generated method stub   
  24.         return null;  
  25.     }  
  26.   
  27.     @Override  
  28.     public void onCreate() {  
  29.         // TODO Auto-generated method stub   
  30.         super.onCreate();  
  31.           
  32.         mServiceThread = new Thread(new SocketServerThread());  
  33.     }  
  34.   
  35.     @Override  
  36.     public void onStart(Intent intent, int startId) {  
  37.         // TODO Auto-generated method stub   
  38.         super.onStart(intent, startId);  
  39.           
  40.         mServiceThread.start();  
  41.     }  
  42.   
  43.     @Override  
  44.     public void onDestroy() {  
  45.         // TODO Auto-generated method stub   
  46.         super.onDestroy();  
  47.     }  
  48.   
  49.     public class SocketServerThread extends Thread {  
  50.         private static final int PORT = 54321;  
  51.           
  52.         private SocketServerThread(){  
  53.         }  
  54.           
  55.         @Override  
  56.         public void run() {  
  57.             try {  
  58.                 ServerSocket server = new ServerSocket(PORT);  
  59.                   
  60.                 while(true){  
  61.                     System.out.println("begin client connected");  
  62.                     client = server.accept();  
  63.                     System.out.println("client connected");  
  64.                       
  65.                     BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));  
  66.                     System.out.println("read from client:");  
  67.                       
  68.                     String textLine = reader.readLine();  
  69.                     if(textLine.equalsIgnoreCase("EXIT")){  
  70.                         System.out.println("EXIT invoked, closing client");  
  71.                         break;  
  72.                     }  
  73.   
  74.                     System.out.println(textLine);  
  75.                       
  76.                     PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())));  
  77.                       
  78.                     writer.println("ECHO from server: " + textLine);  
  79.                     writer.flush();  
  80.                       
  81.                     writer.close();  
  82.                     reader.close();  
  83.                 }                             
  84.             } catch (IOException e) {  
  85.                 // TODO Auto-generated catch block   
  86.                 System.err.println(e);  
  87.             }     
  88.         }  
  89.           
  90.     }  
  91. }  
package com.android.sample.SocketServerDemo;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class SocketService extends Service{
	Thread mServiceThread;
	
	Socket client;
	
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		
		mServiceThread = new Thread(new SocketServerThread());
	}

	@Override
	public void onStart(Intent intent, int startId) {
		// TODO Auto-generated method stub
		super.onStart(intent, startId);
		
		mServiceThread.start();
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
	}

	public class SocketServerThread extends Thread {
		private static final int PORT = 54321;
		
		private SocketServerThread(){
		}
		
		@Override
		public void run() {
			try {
				ServerSocket server = new ServerSocket(PORT);
				
				while(true){
					System.out.println("begin client connected");
					client = server.accept();
					System.out.println("client connected");
					
					BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
					System.out.println("read from client:");
					
					String textLine = reader.readLine();
					if(textLine.equalsIgnoreCase("EXIT")){
						System.out.println("EXIT invoked, closing client");
						break;
					}

					System.out.println(textLine);
					
					PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())));
					
					writer.println("ECHO from server: " + textLine);
					writer.flush();
					
					writer.close();
					reader.close();
				}							
			} catch (IOException e) {
				// TODO Auto-generated catch block
				System.err.println(e);
			}	
		}
	    
	}
}

    3)、AndroidManifest.xml文件,因为需要在其中添加service和网络访问权限,这里一并贴出

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.       package="com.android.sample.SocketServerDemo"  
  4.       android:versionCode="1"  
  5.       android:versionName="1.0">  
  6.     <uses-sdk android:minSdkVersion="9" />  
  7.   
  8.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  9.         <activity android:name=".ScreenCastServer"  
  10.                   android:label="@string/app_name">  
  11.             <intent-filter>  
  12.                 <action android:name="android.intent.action.MAIN" />  
  13.                 <category android:name="android.intent.category.LAUNCHER" />  
  14.             </intent-filter>  
  15.         </activity>  
  16.           
  17.         <service android:name="com.android.sample.SocketServerDemo.SocketService">  
  18.         </service>  
  19.   
  20.     </application>  
  21.       
  22.     <uses-permission android:name="android.permission.INTERNET"/>  
  23. </manifest>  
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.android.sample.SocketServerDemo"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="9" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".ScreenCastServer"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <service android:name="com.android.sample.SocketServerDemo.SocketService">
        </service>

    </application>
    
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>

4、客户端程序

    1)、布局文件main.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7.     <TextView  
  8.         android:id="@+id/receive_msg"   
  9.         android:layout_width="fill_parent"   
  10.         android:layout_height="wrap_content"   
  11.         />  
  12.           
  13.     <EditText  
  14.         android:id="@+id/edit_msg"  
  15.         android:layout_width="fill_parent"  
  16.         android:layout_height="wrap_content"  
  17.         />  
  18.       
  19.     <Button  
  20.         android:id="@+id/send_msg"  
  21.         android:layout_width="wrap_content"  
  22.         android:layout_height="wrap_content"  
  23.         android:text="send"  
  24.         />  
  25. </LinearLayout>  
<?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/receive_msg" 
	    android:layout_width="fill_parent" 
	    android:layout_height="wrap_content" 
	    />
	    
	<EditText
		android:id="@+id/edit_msg"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		/>
	
	<Button
		android:id="@+id/send_msg"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="send"
		/>
</LinearLayout>

    2)、Activity文件SocketClientDemo.java

  1. package com.android.sample.SocketClientDemo;  
  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.OutputStreamWriter;  
  8. import java.io.PrintWriter;  
  9. import java.net.Socket;  
  10. import java.net.UnknownHostException;  
  11.   
  12. import android.app.Activity;  
  13. import android.os.Bundle;  
  14. import android.view.View;  
  15. import android.view.View.OnClickListener;  
  16. import android.widget.Button;  
  17. import android.widget.EditText;  
  18. import android.widget.TextView;  
  19.   
  20. public class SocketClientDemo extends Activity {  
  21.     private static final String SERVERIP = "192.168.1.68";  
  22.     private static final int SERVERPORT = 54321;  
  23.       
  24.     TextView mMsgRev;  
  25.     EditText mMsgEdit;  
  26.     Button   mMsgSendBtn;  
  27.       
  28.     String mSendMsg;  
  29.     String mReceivedMsg;  
  30.       
  31.     /** Called when the activity is first created. */  
  32.     @Override  
  33.     public void onCreate(Bundle savedInstanceState) {  
  34.         super.onCreate(savedInstanceState);  
  35.         setContentView(R.layout.main);  
  36.           
  37.         mMsgRev = (TextView)findViewById(R.id.receive_msg);  
  38.         mMsgEdit = (EditText)findViewById(R.id.edit_msg);  
  39.         mMsgSendBtn = (Button)findViewById(R.id.send_msg);  
  40.           
  41.         mMsgSendBtn.setOnClickListener(new OnClickListener(){  
  42.             @Override  
  43.             public void onClick(View v) {  
  44.                 Socket socket = null;  
  45.                 mSendMsg = mMsgEdit.getText().toString();  
  46.                   
  47.                 try {  
  48.                     socket = new Socket(SERVERIP, SERVERPORT);  
  49.                       
  50.                     PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));  
  51.                     writer.println(mSendMsg);  
  52.                     writer.flush();  
  53.                       
  54.                     BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));   
  55.                     mReceivedMsg = reader.readLine();  
  56.                     if(mReceivedMsg != null){  
  57.                         mMsgRev.setText(mReceivedMsg);  
  58.                     }else{  
  59.                         mMsgRev.setText("receive data error");  
  60.                     }  
  61.                       
  62.                     writer.close();  
  63.                     reader.close();  
  64.                     socket.close();  
  65.                 } catch (UnknownHostException e) {  
  66.                     // TODO Auto-generated catch block   
  67.                     e.printStackTrace();  
  68.                 } catch (IOException e) {  
  69.                     // TODO Auto-generated catch block   
  70.                     e.printStackTrace();  
  71.                 }  
  72.             }             
  73.         });  
  74.     }  
  75. }  
package com.android.sample.SocketClientDemo;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class SocketClientDemo extends Activity {
	private static final String SERVERIP = "192.168.1.68";
	private static final int SERVERPORT = 54321;
	
	TextView mMsgRev;
	EditText mMsgEdit;
	Button   mMsgSendBtn;
	
	String mSendMsg;
	String mReceivedMsg;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        mMsgRev = (TextView)findViewById(R.id.receive_msg);
        mMsgEdit = (EditText)findViewById(R.id.edit_msg);
        mMsgSendBtn = (Button)findViewById(R.id.send_msg);
        
        mMsgSendBtn.setOnClickListener(new OnClickListener(){
			@Override
			public void onClick(View v) {
				Socket socket = null;
				mSendMsg = mMsgEdit.getText().toString();
				
				try {
					socket = new Socket(SERVERIP, SERVERPORT);
					
					PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
					writer.println(mSendMsg);
					writer.flush();
					
					BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));	
					mReceivedMsg = reader.readLine();
					if(mReceivedMsg != null){
						mMsgRev.setText(mReceivedMsg);
					}else{
						mMsgRev.setText("receive data error");
					}
					
					writer.close();
					reader.close();
					socket.close();
				} catch (UnknownHostException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}        	
        });
    }
}

    3)、在AndroidManifest.xml中向服务器端的该文件一样,添加网络访问权限:<uses-permission android:name="android.permission.INTERNET"/>


5、执行环境搭建

        服务端程序在开发板上执行,客户端程序在模拟器上执行,实现了基于Socket的数据收发。但是我这里只是进行了局域网内的通信,至于跨网络能不能行,目前条件不够,没法进行验证。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值