android 通信机制 socket

  socket 作为一种通信机制,可以实现单机或者跨网络之间的通信,要有明确的server端和client端。

android里面最简单的socket 通信的demo:

//1. IP 地址

InetAddress inetAddress = InetAddress.getByName("IP address");

// socket port

Socket client = new Socket(inetAddress,61203,true);

// get data stream

InputStream in = client.getInputStream();

OutputStream out = client.getOutputStream();

// deal with data

// close connection

out.close();

in.close();

client.close();

   在一个完整的通行过程,包括2个socket,一个server段在用,另外一个是client段。整个架构的简介:

    1)通常情况下,我们使用线程处理socket携带的信息。
    2)clientThread, serverThread处理socket,好处是主线程可以继续其他的工作。

  demo创建的流程:1. 在Eclipse里面安装Tomcat 作为server

           2. 编写一个service project用来处理client 传递过来的数据,并且把处理过的数据返回到客户端

           3. 编写一个简单的android应用,向service发送数据,并且接收service返回的数据

  1. 如何在Eclipse里面配置Tomcat不是本文的重点,在网上搜索一堆。这里要说明的如果默认的8080端口被使用,要修改Tomcat配置文件里面的端口号,配置文件的地址是../conf/server.xml

 <Connector port="80" protocol="HTTP/1.1"  connectionTimeout="20000" redirectPort="8443"/>

这个只是Tomcat的端口,和socket里面的端口不一样。

  2. Server的端代码:

   1)ServerThread

  public class SeverThread implements Runnable

  {

    private Socket socket=null; // 定义一个socket 给当前线程使用

    private BufferedReader br=null; // 处理线程里面socket所对应的输入流

    public ServerThread(Socket socket)

    {

      this.socket=socket;

      // 初始化socket对应的流

      br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"utf-8"));

    }

    public void run()

    {

      String content="";

      // 不停的loop, 读取client传过的数据

      while((content = getContent())!= null){

        // 读取socket里面的内容,然后回发, 这里是整个server的核心,也是功能扩展的核心

        for(Socket s : MyServer.socketList){

          OutputStream os = s.getOutputStream(); // outputStream 是用socket创建

          os.write(("这个server段给你的消息").getBytes("utf-8"))

        }

      }

    }

    private String getContent()

    {

      try{

          return br.readLine();

        }catch(Exception ex){

          MyServer.socketList.remove(socket);// 如果捕获到异常,表明要关闭这个client的连接, 删除该socket

        }

        return null;

    }

  }

 定义好一个serverThread,我们就开始在编写service app,定义一个简单的控制台应用即可,host在tomcat上。

public class MyServer{

  public List<Socket> socketList = new ArrayList<Socket>();

  public static void main(){

    ServerSocket ss = new ServerSocket(18070) ;// 这里的18070是端口号,这个是client 和server 公用的端口号

    // 程序开始不停的loop,等待client的连接

    while(true){

      Socket s = ss.accept();

      socketList.add(s);

      // 有client的socket过来的时候启动线程处理

      new Thread(new ServerThread(s)).start();

    }

  }

}

至此server段的代码已经编写完毕,启动Tomcat,启动server的application host在Tomcat上,一个完整的service已经好了。

  3. 编写client段, client段的结构和server类似,一个clientThread,一个android application

public class ClientThread implements Runnable{

  private Socket socket; //为这个线程定义一个socket 

  private BufferedReader br = null;// 处理该线程的socket流

  private Handler handler;// 作用是发送message到UI,通知UI改变信息

  public ClientThread(Socket socket, Handler handler) throw IOException

  {

    this.socket  = socket;

    this.handler=handler;

    br=new BufferedReader(new InputStreamReader(sockt.getInputStream()));

  }

  public void run(){

    try{

      String content="";

      // 和server相同,不停的循环读取socket里面的流

      while((content=br.readLine())!=null){

          // 读到数据之后,发送message,通知UI改变

          Message msg = new Message();

          msg.what=0X123; // 作为message的标识

          msg.object= content;

          handler.sendMessage(msg);

      }

    }catch(Exception ex){

      e.printStackTrace();

    }

  }

}

 

public class MainActivity extends Activity implements Runnable {

private Button btnTest;
private TextView tv_msg;
private EditText etMessage;
private String content = "";
Handler handler;
// 需要BufferedReader
BufferedReader bufferedReader = null;
// 需要一个socket
Socket socket = null;
// 需要一个printWritter
PrintWriter out = null;
OutputStream os;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// 如果是2.3以后的版本,这段必须加上
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads().detectDiskWrites().detectNetwork() /
.penaltyLog().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects().penaltyLog().penaltyDeath()
.build());

handler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
// 如果消息来自于子线程
if (msg.what == 0x123)
{
// 将读取的内容追加显示在文本框中
tv_msg.append("\n" + msg.obj.toString());
}
}
};
initalView();
btnTest.setOnClickListener(myListener);
new Thread(MainActivity.this).start();
}

private void initalView() {
btnTest = (Button) findViewById(R.id.btnTest);
etMessage = (EditText) findViewById(R.id.messageET);
tv_msg = (TextView) findViewById(R.id.tv_msg);
initalSocket();
}

private void initalSocket() {
try {
socket = new Socket();
InetSocketAddress sd = new InetSocketAddress(HostPort.HOST,HostPort.PORT);
socket.connect(sd,5000);
new Thread(new ClientThread(socket, handler)).start(); // ①
os = socket.getOutputStream();
} catch (UnknownHostException e) {
// 由于会发生断网什么的异常处理
System.out.print("连接不上了");
e.printStackTrace();
} catch (IOException e) {
System.out.print(e.getMessage());
e.printStackTrace();
}
}

private View.OnClickListener myListener = new View.OnClickListener() {

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnTest:
testSocket();

break;
}

}
};

private void testSocket() {
// 将用户在文本框内输入的内容写入网络
try {
os.write((etMessage.getText().toString() + "\r\n")
.getBytes("utf-8"));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 清空input文本框
etMessage.setText("");

}

@Override
public void run() {

}

@SuppressLint("HandlerLeak")
public Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.println(1, "test", msg.toString());
tv_msg.setText(tv_msg.getText().toString() + content);
}
};

}

同时在manifest.xml文件中添加权限<uses-permission android:name="android.permission.INTERNET" />

启动android application 即可用socket通行。

以上这种方式其实质就是TCP/IP协议的网络通信。 TCP/IP通信的运行机制是首先向对方发出询问,在等到对方的response后,就给对方发数据。还有一种是UDP的通信,将在下一篇文章详细介绍。 这种UDP的通信方式的缺陷是,不知道对方通不通,就给对方发送消息,结果就是有可能丢包。

 

如要转载,请注明出处

posted @ 2013-05-25 23:49  heavenliu  阅读(2367)  评论(0编辑  收藏  举报