`

Android学习13-----网络通信(2) 与Socket交换数据

阅读更多

对于网络开发而言,最常用的交互模式:WebService、Web Server、Socket程序,一些Socket程序的使用要比JSP/Servlet等程序更加安全,所以在许多的Android手机端都会利用Socket进行数据的交互。
下面我们来完成一个简单的Echo程序
首先定义服务器端程序,MyServer.java

package com.iflytek.server;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author xdwang
 * 
 * @create 2012-11-16 下午9:46:04
 * 
 * @email:xdwangiflytek@gmail.com
 * 
 * @description Socket 服务
 * 
 */
public class MyServer {

	public static void main(String[] args) {
		try {
			ServerSocket server = new ServerSocket(8888);// 在8888端口上监听
			Socket client = server.accept();// 接受客户端请求
			PrintStream out = new PrintStream(client.getOutputStream());// 取得客户端输出流
			BufferedReader buf = new BufferedReader(new InputStreamReader(
					client.getInputStream()));// 字符缓冲区读取
			StringBuffer info = new StringBuffer();// 接受客户端的信息
			info.append("Android:");// 回应数据
			info.append(buf.readLine());// 接受数据
			out.print(info);// 发送信息
			out.close();
			buf.close();
			client.close();
			server.close();

		} catch (Exception e) {
		}
	}
}

Android客户端,Socket01_EchoActivity.java

package com.iflytek.demo;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class Socket01_EchoActivity extends Activity {

	private Button send = null;
	private TextView infoTxt = null;

	public Handler handler = new Handler() {
		@Override
		public void handleMessage(android.os.Message msg) {
			super.handleMessage(msg);
			switch (msg.what) {
			case 1:
				infoTxt.setText(msg.obj.toString());
				break;
			default:
				break;
			}
		}
	};

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		this.send = (Button) super.findViewById(R.id.send);
		this.infoTxt = (TextView) super.findViewById(R.id.info);
		this.send.setOnClickListener(new SendOnClickListener());
	}

	private class SendOnClickListener implements OnClickListener {
		@Override
		public void onClick(View v) {

			final AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {

				@Override
				protected void onPostExecute(String result) {
					final String temp = result;
					Thread thread = new Thread(new Runnable() {
						@Override
						public void run() {
							Message msg = new Message();
							msg.what = 1;
							msg.obj = temp;
							handler.sendMessage(msg);
						}
					});
					thread.start();
				}

				@Override
				protected void onPreExecute() {
					super.onPreExecute();
				}

				@Override
				protected String doInBackground(Void... arg0) {
					String result = "";
					try {
						Socket client = new Socket("IP", 8888);// 指定服务器
						PrintStream out = new PrintStream(
								client.getOutputStream());// 打印流输出
						BufferedReader buf = new BufferedReader(
								new InputStreamReader(client.getInputStream()));// 缓冲区读取
						out.println("王旭东"); // 向服务器端发送数据
						result = buf.readLine();
						out.close();
						buf.close();
						client.close();
					} catch (Exception e) {
						e.printStackTrace();
					}
					return result;
				}
			};
			task.execute();

		}
	}
}

AndroidManifest.xml同样需要访问网络的权限

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

其实在Android之中所编写的客户端代码与在java中所编写的Socket程序的客户端代码的功能是完全一样的,没有任何区别。

Ok,我们再来看看利用Socket进行上传操作,在完成上传的同时,附加多种数据如文件标题、大小等。
其实现方式:
1、我们可以直接将所有数据通过字节数组传送,如果采用这种方式,则需要传送两类数据,一种数据类型是自定义的头信息(如文件类型、大小等都通过头信息传递);另一种数据类型才是真正要上传的文件内容。但是这样做在服务器端的接收会比较麻烦,因为所有的数据都是按照字节流的方式传输的,所以必须在各种不同的数据间设置分隔符,而后取出数据时必须处理掉这些分隔符。
2、通过对象序列化的方法完成,使用一个专门的长传数据封装类,将所有的数据内容、文件内容(以字节数组保存)进行封装,而后利用对象序列化的方式,将该对象送到服务器端。使用这种方式处理较为容易,也很方便。

首先定义包装数据的序列化对象类,UploadFile.java

package com.iflytek.util;

import java.io.Serializable;

/**
 * @author xdwang
 * 
 * @create 2012-11-16 下午10:39:01
 * 
 * @email:xdwangiflytek@gmail.com
 * 
 * @description 数据的序列化对象类,进行序列化传输
 * 
 */
@SuppressWarnings("serial")
public class UploadFile implements Serializable {
	private String title;//信息标题
	private byte[] contentData;//文件内容
	private String mimeType;//文件类型
	private long contentLength;//文件长度
	private String ext;//扩展名

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public byte[] getContentData() {
		return contentData;
	}

	public void setContentData(byte[] contentData) {
		this.contentData = contentData;
	}

	public String getMimeType() {
		return mimeType;
	}

	public void setMimeType(String mimeType) {
		this.mimeType = mimeType;
	}

	public long getContentLength() {
		return contentLength;
	}

	public void setContentLength(long contentLength) {
		this.contentLength = contentLength;
	}

	public String getExt() {
		return ext;
	}

	public void setExt(String ext) {
		this.ext = ext;
	}
}

然后服务器端也要一个相同的类

服务器端服务类,MyServer02.java

package com.iflytek.server;

import java.net.ServerSocket;

public class MyServer02 {
	public static void main(String[] args) {
		try {
			String ss = "";
			System.out.println(ss);
			// 调用线程类启动服务
			ServerSocket server = new ServerSocket(8889); // 服务器端端口
			boolean flag = true; // 定义标记,可以一直死循环
			while (flag) { // 通过标记判断循环
				new Thread(new ServerThreadUtil(server.accept())).start(); // 启动线程
			}
			server.close(); // 关闭服务器
		} catch (Exception e) {
		}
	}
}

服务器端的多线程操作类,ServerThreadUtil.java

package com.iflytek.server;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.UUID;

import com.iflytek.util.UploadFile;

/**
 * @author xdwang
 * 
 * @create 2012-11-16 下午10:49:46
 * 
 * @email:xdwangiflytek@gmail.com
 * 
 * @description 多线程操作类
 * 
 */
public class ServerThreadUtil implements Runnable {
	private static final String DIRPATH = "D:" + File.separator + "xdwang"
			+ File.separator; // 保存文件夹
	private Socket client = null;//接受客户端
	private UploadFile uploadFile = null;//传递对象

	public ServerThreadUtil(Socket client) {//通过构造方法设置Socket
		this.client = client;
		System.out.println("新的客户端连接...");
	}

	@Override
	public void run() {
		try {
			PrintStream out = new PrintStream(this.client.getOutputStream());//取得客户端的输出流
			ObjectInputStream ois = new ObjectInputStream(
					client.getInputStream()); // 取得客户端的输入流,反序列化
			this.uploadFile = (UploadFile) ois.readObject(); // 读取对象
			System.out.println("文件标题:" + this.uploadFile.getTitle());
			System.out.println("文件类型:" + this.uploadFile.getMimeType());
			System.out.println("文件大小:" + this.uploadFile.getContentLength());
			out.print(this.saveFile());//返回标记
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				this.client.close();//关闭客户端连接
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * @descrption 进行文件保存
	 * @author xdwang
	 * @create 2012-11-16下午10:52:18
	 * @return
	 * @throws Exception
	 */
	private boolean saveFile() throws Exception { 
		File file = new File(DIRPATH + UUID.randomUUID() + "."
				+ this.uploadFile.getExt());
		if (!file.getParentFile().exists()) {
			file.getParentFile().mkdir();
		}
		OutputStream output = null;
		try {
			output = new FileOutputStream(file);
			output.write(this.uploadFile.getContentData());
			return true;
		} catch (Exception e) {
			throw e;
		} finally {
			output.close();
		}
	}
}

Android客户端,Socket02_Activity.java

package com.iflytek.demo;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.net.Socket;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.iflytek.util.UploadFile;

public class Socket02_Activity extends Activity {
	private Button send = null;
	private TextView info = null;
	private static final int FINISH = 0;
	private Handler myHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case FINISH:
				String result = msg.obj.toString(); // 取出数据
				if ("true".equals(result)) {
					Socket02_Activity.this.info.setText("操作成功!");
				} else {
					Socket02_Activity.this.info.setText("操作失败!");
				}
				break;
			}
		}
	};

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		this.send = (Button) super.findViewById(R.id.send);
		this.info = (TextView) super.findViewById(R.id.info);
		this.send.setOnClickListener(new SendOnClickListener());
	}

	/**
	 * 
	 * @author xdwang
	 * 
	 * @create 2012-11-16 下午10:44:57
	 * 
	 * @email:xdwangiflytek@gmail.com
	 * 
	 * @description UploadFile封装的数据通过ObjectOutputStream发送到服务器,服务器返回true or flase
	 * 
	 */
	private class SendOnClickListener implements OnClickListener {
		@Override
		public void onClick(View v) {
			try {

				final AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {

					@Override
					protected void onPostExecute(String result) {
					}

					@Override
					protected void onPreExecute() {
						super.onPreExecute();
					}

					@Override
					protected String doInBackground(Void... arg0) {
						try {
							final Socket client = new Socket("10.0.0.3", 8889);// 指定服务器
							final BufferedReader buf = new BufferedReader(
									new InputStreamReader(
											client.getInputStream())); // 缓冲区读取返回的数据
							new Thread(new Runnable() {// 创建线程对象

										@Override
										public void run() {
											try {
												ObjectOutputStream oos = new ObjectOutputStream(
														client.getOutputStream());// 对象输出流
												UploadFile myFile = SendOnClickListener.this
														.getUploadFile();// 取得封装的数据
												oos.writeObject(myFile);// 输出对象
												String str = buf.readLine(); // 读取返回数据
												oos.close();
												Message msg = Socket02_Activity.this.myHandler
														.obtainMessage(FINISH,
																str);
												Socket02_Activity.this.myHandler
														.sendMessage(msg);
												buf.close();
												client.close();
											} catch (Exception e) {
												e.printStackTrace();
											}
										}
									}).start();
						} catch (Exception e) {
							// TODO: handle exception
						}
						return null;
					}
				};
				task.execute();

			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		/**
		 * @descrption 封装数据的方法
		 * @author xdwang
		 * @create 2012-11-15下午10:46:06
		 * @return
		 * @throws Exception
		 */
		private UploadFile getUploadFile() throws Exception {
			UploadFile myFile = new UploadFile();// 上传封装
			myFile.setTitle("Java"); // 设置标题
			myFile.setMimeType("image/jpeg"); // 文件的类型
			File file = new File(Environment.getExternalStorageDirectory()
					.toString() + File.separator + "java.jpg");// 这里不判断SDCard了
			InputStream input = null;// 输入流读取
			try {
				input = new FileInputStream(file); // 从文件中读取
				ByteArrayOutputStream bos = new ByteArrayOutputStream();// 字节流
				byte data[] = new byte[1024];// 开辟读取空间
				int len = 0;
				while ((len = input.read(data)) != -1) {// 循环读取
					bos.write(data, 0, len);// 保存数据
				}
				myFile.setContentData(bos.toByteArray());// 保存所有数据
				myFile.setContentLength(file.length());// 取得文件大小
				myFile.setExt("jpg");// 文件后缀名
			} catch (Exception e) {
				throw e;
			} finally {
				input.close();
			}
			return myFile;
		}

	}

}
分享到:
评论

相关推荐

    android-socket-nio-master.zip

    在Android开发中,Socket通信是应用层与传输层之间的接口,用于实现设备间的网络通信。传统的Socket通信通常基于BIO(Blocking I/O)模型,但随着高性能和高并发需求的增加,开发者开始转向NIO(Non-blocking I/O)...

    Android-Lemon一个简单轻量级的AndroidSocket框架

    在Android应用开发中,网络通信是必不可少的一部分,而Socket通信则是实现客户端与服务器间低层次、高效能数据交换的重要手段。`Android-Lemon`是一个专为Android设计的简单、轻量级的Socket框架,它简化了Socket...

    Android-Pc-Socket-Connection源码

    通过学习和理解这个"Android-Pc-Socket-Connection"源码,开发者可以掌握Android与PC间的网络通信技术,为构建更复杂的跨平台应用程序打下基础。实践中,你可能会遇到网络延迟、数据解析、并发处理等问题,这些都是...

    网络编程课程设计报告-Android-Socket-聊天室.doc

    - **Socket通信**:基于TCP/IP协议,通过两端建立Socket连接形成虚拟链路,实现两端程序的数据交换。 - **服务器端工作流程**: - 创建并绑定Socket到特定端口。 - 设置监听模式等待连接请求。 - 接受连接并...

    Android开发,Socket Client端和Socket Server端数据发送和接收

    在Android开发中,Socket通信是实现设备间网络通信的一种常见方式。Socket分为客户端(Socket Client)和服务器端(Socket Server),它们共同构成了基于TCP/IP协议的通信模型。本篇文章将详细探讨Android环境下如何...

    C#与Android Socket通信

    Socket通信是一种基于TCP/IP协议族的网络通信方式,它允许两个网络应用程序通过网络进行数据交换。在本场景中,我们关注的是C#作为服务器端,Android作为客户端的Socket通信实现。这种通信方式常用于移动应用与后台...

    Android基于局域网socket通信

    Socket是网络通信的一种接口,它提供了进程间通信(IPC)的能力,让两个设备能够通过Internet协议(IP)地址和端口号建立连接。在Android中,我们可以使用Java的内置Socket类来实现这一功能。 要构建一个Android...

    android+pc socket通信

    "Android+PC Socket通信"指的是通过TCP Socket协议实现Android设备(手机客户端)与个人计算机之间的数据传输。Socket通信允许应用程序之间建立端到端的连接,进行双向数据交换,非常适合用于实时通讯、文件传输等...

    Android Wifi热点 数据传输Socket 通信

    Socket是网络通信中的基础组件,它为两台设备之间的数据交换提供了一种可靠的接口。在Android设备上,我们可以通过创建一个服务器Socket监听特定端口,然后用客户端Socket连接到这个服务器,从而实现数据的发送和...

    Android学习之Socket通信

    首先,Socket 作为网络通信的核心组件,它代表了两台计算机之间进行数据交换的连接点。在 IP 地址和端口号的组合下,Socket 能够标识网络上的唯一进程。Socket 提供了两种主要的通信模式:面向连接(TCP)和无连接...

    Android笔记:Socket客户端收发数据

    在Android开发中,Socket通信是实现设备间数据传输的重要手段,尤其在构建网络服务和进行设备间的实时交互时。本文将深入探讨如何在Android平台上创建一个Socket客户端,以及如何通过TCP协议进行数据的发送和接收。 ...

    android 安卓手机与电脑socket通信

    在Android平台上,实现安卓手机与电脑之间的通信是一个常见的需求,特别是在进行远程控制、数据传输或者游戏同步等场景。本教程将深入探讨如何使用Socket通信来连接安卓设备与个人计算机。Socket,也被称作套接字,...

    Android-Socket长连接通信心跳包消息回调Java服务端

    在Android开发中,网络编程是不可或缺的一部分,尤其是对于需要实时通信的应用来说,Socket长连接尤为重要。...通过理论学习和实际项目的实践,开发者可以掌握这些技能,为构建稳定、高效的网络通信系统奠定基础。

    android app与pc通信,USB连接socket通信,

    在IT行业中,Android App与PC通信是一个常见的需求,特别是在特定环境下如无WiFi网络或需要高度安全性的场景。本文将深入探讨如何通过USB连接实现Android应用与个人计算机(PC)之间的Socket通信。 首先,理解...

    android socket通信demo

    - **Socket接口**:Socket是Java提供的网络通信API,它为应用程序提供了一种在网络间发送和接收数据的方法。 - **TCP与UDP**:Socket分为两种类型,TCP(Transmission Control Protocol)和UDP(User Datagram ...

    Android socket通信聊天,客户端+服务端

    Socket是网络通信中的一个编程接口,它允许两台计算机通过网络进行数据交换。在Android中,我们可以使用Java的Socket类来实现这一功能。Java的Socket类提供了一种基于TCP/IP协议的连接,保证了数据的可靠传输。 **...

    Android中Socket通信

    Socket是网络通信中的一个端点,它允许两个应用程序通过网络进行数据交换。在Android中,我们通常使用java.net.Socket和ServerSocket类来创建和管理Socket连接。ServerSocket用于监听客户端的连接请求,而Socket则...

    android socket通信实例程序

    在Android平台上进行网络通信时,Socket通信是一种常见且重要的方式,尤其在实现设备间的数据交换、服务器客户端交互等场景。本实例程序主要涉及到的是Android应用如何利用Socket进行TCP(Transmission Control ...

    Android-Socket登录实例

    本实例主要探讨如何在Android环境中使用Socket进行登录功能的实现,这对于理解网络编程的基本原理和Android网络API的使用具有重要意义。 首先,我们要明白Socket的概念。Socket,也被称为套接字,是网络编程中的一...

    android中java和C的socket通信demo

    Java中的`java.net.Socket`类提供了网络通信的能力,它允许我们在两个应用程序之间建立全双工的、可靠的连接。在Java中,我们可以通过`Socket`对象创建一个连接到指定服务器的套接字,并使用`Socket....

Global site tag (gtag.js) - Google Analytics