Android网络编程概述
首先,了解的几个问题:
1、Android系统网络相关API接口
1)、java.net.*(标准Java接口)
java.net.*提供与联网有关的类,包括流、数据包套接字(socket)、internet协议、常见Http处理等。比如创建URL,以及URLConnection/HTTPURLConnection对象、设置链接参数、链接到服务器、向服务器写数据、从服务器读取数据等通信。这些在Java网络编程中均有涉及。
2)、Org.apache接口
对于大部分应用程序而言JDK本身提供的网络功能已远远不够,这时就需要Android提供的Apache HttpClient了。它是一个开源项目,功能更加完善,为客户端的Http编程提供高效、最新、功能丰富的工具包支持。
3)、Android.net.*(Android网络接口)
常常使用此包下的类进行Android特有的网络编程,如:访问WIFI,访问Android联网信息,邮件等功能。
2、网络架构主要有两种模式B/S、C/S
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.List;
public class MyServer{
//定义保存所有的Socket,与客户端建立连接得到一个Socket
public static List socketList = new ArrayList();
public static void main(String[] args) throws IOException{
ServerSocket server = new ServerSocket(8888);
while (true){
System.out.println("start listening port 8888.");
Socket socket = server.accept();
System.out.println("connect succeed.");
socketList.add(socket);
//每当客户端连接之后启动一条ServerThread线程为该客户端服务
new Thread(new MyServerRunnable(socket)).start();
}
}
public static class MyServerRunnable implements Runnable {
//定义当前线程处理的Socket
Socket socket = null;
//该线程所处理的Socket所对应的输入流
BufferedReader bufferedReader = null;
public MyServerRunnable(Socket socket){
this.socket = socket;
try {
//将服务器端的输入流的数据放入读Buffer中
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}catch (IOException e){
e.printStackTrace();
}
}
public void run(){
String content = null;
//采用循环不断的从Socket中读取客户端发送过来的数据
while ((content = readFromClient()) != null){
//遍历socketList中的每一个Socket,将读取的内容向每个Socket发送一次
for (Socket socket:MyServer.socketList) {
OutputStream outputStream;
try {
outputStream = socket.getOutputStream();
outputStream.write((content+"\n").getBytes("utf-8"));
}catch (IOException e){
e.printStackTrace();
}
}
}
}
// 定义读取客户端的信息
public String readFromClient() {
try {
return bufferedReader.readLine();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
}
客户端——Android代码
activity_main.xml
ClientThread.java
package com.example.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
public class ClientThread implements Runnable {
private Socket s;
// 定义向UI线程发送消息的Handler对象
Handler handler;
// 定义接收UI线程的Handler对象
Handler revHandler;
// 该线程处理Socket所对用的输入输出流
BufferedReader br = null;
OutputStream os = null;
public ClientThread(Handler handler) {
this.handler = handler;
}
@SuppressLint("HandlerLeak") @Override
public void run() {
// TODO Auto-generated method stub
try {
s = new Socket();
Log.d("111111111111", "@@@@@@@@@@@@@@@@@@@@");
// s = new Socket("192.168.0.78", 8888);//此方法不能设定连接时限
s.connect(new InetSocketAddress("192.168.0.78", 8888), 5000);
Log.d("111111111111", "$$$$$$$$$$$$$$$$$$");
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
os = s.getOutputStream();
// 启动一条子线程来读取服务器相应的数据
new Thread() {
@Override
public void run() {
String content = null;
// 不断的读取Socket输入流的内容
try {
while ((content = br.readLine()) != null) {
// 每当读取到来自服务器的数据之后,发送的消息通知程序
// 界面显示该数据
Message msg = new Message();
msg.what = 0x123;
msg.obj = content;
handler.sendMessage(msg);
Log.d("111111111111", content);
}
} catch (IOException io) {
io.printStackTrace();
}
}
}.start();
// 为当前线程初始化Looper
Looper.prepare();
// 创建revHandler对象
revHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 接收到UI线程的中用户输入的数据
if (msg.what == 0x345) {
// 将用户在文本框输入的内容写入网络
try {
os.write((msg.obj.toString() + "\r\n")
.getBytes("utf-8"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
// 启动Looper
Looper.loop();
} catch (SocketTimeoutException e) {
Message msg = new Message();
msg.what = 0x123;
msg.obj = "网络连接超时!";
handler.sendMessage(msg);
} catch (IOException io) {
io.printStackTrace();
}
}
}
MainActivity.java
package com.example.socket;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
Handler handler;
// 定义与服务器通信的子线程
ClientThread clientThread;
TextView show;
Button send;
@SuppressLint("HandlerLeak") @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
show = (TextView)this.findViewById(R.id.show);
send = (Button)this.findViewById(R.id.send);
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
try {
// 当用户按下按钮之后,将用户输入的数据封装成Message
// 然后发送给子线程Handler
Message msg = new Message();
msg.what = 0x345;
msg.obj = "Android 网络编程--Socket通信编程";
clientThread.revHandler.sendMessage(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
});
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
// 如果消息来自子线程
if (msg.what == 0x123) {
// 将读取的内容追加显示在文本框中
show.append("\n" + msg.obj.toString());
show.setTextSize(50);
}
}
};
clientThread = new ClientThread(handler);
// 客户端启动ClientThread线程创建网络连接、读取来自服务器的数据
new Thread(clientThread).start();
}
}
测试: