Android应用开发基础篇(12)-----Socket通信(转载)
转自:http://www.devdiv.com/android_socket_-blog-258060-10594.html
一、概述
网络通信无论在手机还是其他设备上都应用得非常广泛,因此掌握网络编程是非常有必要的,而我觉得socket编程是网络编程的基础。在进入正题之前,先介 绍几点网络知识,一:socket编程有分TCP和UDP两种,TCP是基于连接的,而UDP是无连接的;二:一个TCP连接包括了输入和输出两条独立的 路径;三:服务器必须先运行然后客户端才能与它进行通信。四:客户端与服务器所使用的编码方式要相同,否则会出现乱码。下面的实现中为了讲解的方便,并没有采用多线程的方法,因此通信过程中会阻塞UI线程,而且只涉及了单向通信(客户端-->服务器),完善的程序(多线程,双向通信)会在提高篇再讲解。
二、要求
熟悉socket编程。
三、实现
新建工程MyClient,修改/res/layout/main.xml文件,在里面添加一个EditText和两个Button,完整的main.xml文件如下:
[代码]xml代码:
<?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" > <EditText android:id="@+id/edittext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="请输入要发送的内容" /> <Button android:id="@+id/connectbutton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="连接" /> <Button android:id="@+id/sendbutton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="发送" /> </LinearLayout>
接着,修改MyClientActivity.java文件,定义一个socket对象和一个OutputStream对象(用于发送数据),完整的内容如下:
[代码]java代码:
package com.nan.client; import java.io.IOException; 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.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MyClientActivity extends Activity { private EditText mEditText = null; private Button connectButton = null; private Button sendButton = null; private Socket clientSocket = null; private OutputStream outStream = null; /** 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); 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("183.41.101.71",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); } }); //发送数据按钮监听 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(); } displayToast("发送成功!"); } }); } //显示Toast函数 private void displayToast(String s) { Toast.makeText(this, s, Toast.LENGTH_SHORT).show(); } }
接着,新建工程MyServer,同样修改/res/layout/main.xml文件,如下:
[代码]xml代码:
<?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/textview" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="15dip" /> </LinearLayout>
修改MyServerActivity.java文件,比较简单,代码中有详细注释,如下:
[代码]java代码:
package com.nan.server; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.ServerSocket; import java.net.Socket; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class MyServerActivity extends Activity { private TextView mTextView = null; private InputStream mInputStream = null; private Socket clientSocket = null; private ServerSocket mServerSocket = null; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mTextView = (TextView)this.findViewById(R.id.textview); 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(); } try { //获得socket的输入流 mInputStream = clientSocket.getInputStream(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } byte[] buf = new byte[512]; String str = null; try { //读取输入的数据(阻塞读) mInputStream.read(buf); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { //字符编码转换 str = new String(buf, "GB2312").trim(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } //显示接收到的数据 mTextView.setText("收到的数据:"+str); } }
最后在两个工程的AndroidMainfest.xml文件中都加入权限:
1 <uses-permission android:name="android.permission.INTERNET"></uses-permission>
到这里,客户端和服务器的程序都写好了,在模拟器上运行客户端程序:
在真机上运行服务器程序:
接着,点击客户端“连接”按钮,输入一些内容再点击“发送”按钮:
此时服务器端的情况如下:
可见成功接收了客户端发送过来的数据。