zoukankan      html  css  js  c++  java
  • Socket通信基础(一)

      Android的Socket通信分为两块,它们分别是TCP和UDP。

      TCP与UDP两者相较而言,TCP是重量级长连接,可靠的,有序的,无边界的,速度较慢;而UDP是轻量级无连接,不可靠,无序,有边界,速度较快。目前的应用场景来说,TCP用于不能出错的场合,如金融、文件传输(其中,金融的FIX协议是基于TCP协议的)。而UDP则是主要运用在语音通话、直播等速度要求很高的地方,中间即便出现小错误,如串音,卡顿一两帧,也不要紧。

      这篇介绍Android端的TCP通信。

      首先,TCP通信是长连接,所以,在开始通信前要三次握手。设备通过IP找到接收端,对指定端口发出数据。接收端需要在指定端口监听,如果接收端没有监听,握手就会失败,发送端能够获知连接被拒。

      然后,我需要知道端收端的IP和监听端口,假设接收的IP是192.168.0.50,监听端口是4444(如果是手机的IP可以在设置中的关于手机里面的手机状态里查看到IP信息)。

      先上发送部分代码

        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.send_btn:
                    String content = editText.getText().toString();
                    if (content == null) {
                        content = "null";
                    }
    
                    final String finalContent = content;
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            connectServerWithTCPSocekt(finalContent, "192.168.0.50", 4444);
                        }
                    }).start();
    
                    break;
            }
        }
    
        private void connectServerWithTCPSocekt(String str, String address, int port) {
            Socket socket = null;
            OutputStream ou = null;
            try {
                //连接服务器 并设置连接超时为5秒
                socket = new Socket();
                socket.connect(new InetSocketAddress(address, port), 5000);
                //获取输出流
                ou = socket.getOutputStream();
                //向服务器发送信息
                if (str != null) {
                    ou.write(str.getBytes("utf-8"));
                } else {
                    ou.write("null".getBytes("utf-8"));
                }
    
            } catch (SocketTimeoutException e) {
                //连接超时 在UI界面显示消息
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (ou != null) {
                        ou.flush();
                        //关闭各种输出流
                        ou.close();
                    }
                    if (socket != null) {
                        socket.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

       我们可以从上面的代码中发现,关于TCP的发送,我们需要写在一个新线程中,不能放入UI线程。因为网络连接不能保证过程的顺利,有可能造成线程阻塞,所以,不能放在UI线程中阻塞UI线程的响应。

      上面代码大致的过程是,新键Socket接,设置连接的IP和端口,后面的5000是超时时间即5秒。然后获取socket的输出流。将想要发送的字符串转成"utf-8"格式的字符数组,然后输出流写字符数组。最后确认输出完毕,关闭输出流、关闭socket连接。

      

      发送部分比较简单,我们再来看看接收部分

     EditText editText;
        Button sendButton;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            editText = (EditText) findViewById(R.id.display_window);
            sendButton = (Button) findViewById(R.id.send_btn);
            sendButton.setOnClickListener(this);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    receiveServerSocketData(4444);
                }
            }).start();
        }
    
        private void receiveServerSocketData(int port) {
            BufferedReader bff = null;
            InputStream input = null;
            Socket socket = null;
            try {
                ServerSocket serivce = new ServerSocket(port);
                while (true) {
                    socket = serivce.accept();
                    String line = null;
    
                    // 获取socket输入流
                    input = socket.getInputStream();
                    bff = new BufferedReader(new InputStreamReader(input));
                    StringBuilder sb = new StringBuilder();
                    // 获取客户端的信息
                    while ((line = bff.readLine()) != null) {
                        // 拼接内容信息
                        sb.append(line);
                        sb.append("
    ");
                    }
                    if (!sb.toString().isEmpty()){
                        sb.deleteCharAt(sb.length() - 1);
                        Message message = Message.obtain();
                        Bundle bundle = new Bundle();
                        bundle.putString("content", sb.toString());
                        message.setData(bundle);
                        message.what = 1001;
                        handler.sendMessage(message);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                // 关闭输入流
                try {
                    if (bff != null) {
                        bff.close();
                    }
                    if (input != null) {
                        input.close();
                    }
                    if (socket != null) {
                        socket.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case 1001:
                        if (msg.getData().getString("content") != null) {
                            editText.setText(msg.getData().getString("content"));
                        } else {
                            editText.setText("null");
                        }
                        break;
                }
            }
        };

      上面的代码分三部分:

      一、开启线程,监听4444端口的消息。

      二、接收Socket数据:

      1、先建ServerSocket;

      2、打开监听阻塞线程,只有接收到消息,线程才会继续;

      3、获取Socket的输入流;

      4、新建BufferedReader;

      5、读取输入流的内容并拼接字符串;

      6、如果读取的内容不为空,将内容通过handler发往UI线程,用于显示;

      7、关闭输入流和Socket。

      三、显示内容。

    至此,就完成了一次简单的TCP发送和接收的过程。

     Done!

    Socket 

    socket = null;
    OutputStream ou = null;
    try {
    //连接服务器 并设置连接超时为5
    socket = new Socket();
    socket.connect(new InetSocketAddress(address, port), 5000);
    //获取输出流
    ou = socket.getOutputStream();
    //向服务器发送信息
    if (str != null) {
    ou.write(str.getBytes("utf-8"));
    } else {
    ou.write("null".getBytes("utf-8"));
    }

    } catch (SocketTimeoutException e) {
    //连接超时 在UI界面显示消息
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    try {
    if (ou != null) {
    ou.flush();
    //关闭各种输出流
    ou.close();
    }
    if (socket != null) {
    socket.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
  • 相关阅读:
    c# mvc action 跳转方式
    where T : new() 的含义
    HTML5 Dataset data-属性
    EF6 教程
    C写的AES(ECB/PKCS5Padding)
    【转载】openwrt: Makefile 框架分析
    SCP 命令【转】
    HTTP协议详解(转载)
    bootstrap模板
    拖拽插件
  • 原文地址:https://www.cnblogs.com/fishbone-lsy/p/5005621.html
Copyright © 2011-2022 走看看