zoukankan      html  css  js  c++  java
  • 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的通信方式的缺陷是,不知道对方通不通,就给对方发送消息,结果就是有可能丢包。

    如要转载,请注明出处

  • 相关阅读:
    protege5.2基础教程
    Controller返回json的编码处理
    QQ开放平台网页应用接口测试
    前端开发工程师
    前端开发工程师
    前端开发工程师
    UniMelb Comp30022 IT Project (Capstone)
    Java开发工程师(Web方向)
    Java开发工程师(Web方向)
    Java开发工程师(Web方向)
  • 原文地址:https://www.cnblogs.com/heavenStrone/p/3095996.html
Copyright © 2011-2022 走看看