安卓开发笔记——Socket使用方法

Android与服务器的通信方式主要有两种:
1.Http通信
2.Socket通信

两者的最大差异在于:
1.Http连接使用的是“请求-响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务端才能向客户端返回数据。
2.Socket通信则是在双方建立连接后,可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端向服务器发送请求。

1.何为Socket?
(1)我们常将Socket翻译为套接字,在程序内部提供与外界通信的端口,即端口通信。通过建立socket连接,可为通信双方的数据传输提供通道;
(2)socket的主要特点有数据丢失率低,使用简单易于移植;
(3)Socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用以实现进程在网络中通信。

2.Socket分类
根据不同的底层协议,Socket的实现是多样化的。这里主要介绍TCP/IP协议簇当中主要的Socket类型:流套接字(streamsocket)和数据报套接字(datagramsocket)。
(1)流套接字将TCP作为其端对端协议,提供了一个可信赖的字节流服务。
(2)数据报嵌套字使用UDP协议,提供数据打包发送数据。

笔者在做物联网智能监控系统APP过程中,需要实现手机客户端向后台服务器端发送Socket,于是写了一个客户端demo,实现三个简单的小功能“连接”、“发送”、“取消连接”:
在这里插入图片描述

(客户端)具体代码为:

Client:

package com.xy.socket;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SocketActivity extends AppCompatActivity {
    private EditText mEditText;
    private TextView mTextView;
    private View view1;
    private View view2;
    private View view3;
    private Button btn1;
    private Button btn2;
    private Button btn3;
    private static final String TAG = "TAG";
    private static final String HOST = "192.168.XXX.XXX";         //ip地址
    private static final int PORT = 12345;                                   //端口号
    private PrintWriter printWriter;
    private BufferedReader in;
    private ExecutorService mExecutorService = null;
    private String receiveMsg;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mEditText = (EditText) findViewById(R.id.mEditText);
        mTextView = (TextView) findViewById(R.id.mTextView);
        btn1 = (Button) findViewById(R.id.btn1);
        btn2 = (Button) findViewById(R.id.btn2);
        btn3 = (Button) findViewById(R.id.btn3);
        mExecutorService = Executors.newCachedThreadPool();
        
        **//为三个按钮设置监听**
        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                connect(view1);
            }
        });
        
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                send(view2);
            }
        });
        
        btn3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                disconnect(view3);
            }
        });
    }

    public void connect(View view) {
        mExecutorService.execute(new connectService());
    }

    public void send(View view) {
        String sendMsg = mEditText.getText().toString();
        Log.e(TAG, ("connectService:" + sendMsg));
        mExecutorService.execute(new sendService(sendMsg));
    }

    public void disconnect(View view) {
        mExecutorService.execute(new sendService("0"));
    }

    private class sendService implements Runnable {
        private String msg;

        sendService(String msg) {
            this.msg = msg;
        }

        @Override
        public void run() {
            printWriter.println(this.msg);
        }
    }

    private class connectService implements Runnable {
        @Override
        public void run() {
            try {
                Socket socket = new Socket(HOST, PORT);
                socket.setSoTimeout(60000);
                printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                socket.getOutputStream(), "UTF-8")), true);
                in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
              } catch (Exception e) {
                Log.e(TAG, ("connectService:" + e.getMessage()));
            }
        }
    }
}

安卓布局文件中只需要添加三个按钮控件以及一个编辑框即可,然后在上述代码中为相应控件添加监听。

布局代码为:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <EditText
    android:id="@+id/mEditText"
    android:layout_width="match_parent"
    android:layout_height="50dp"/>

    <TextView
        android:id="@+id/mTextView"
        android:layout_width="match_parent"
        android:layout_height="50dp"/>

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="连接"/>

    <Button
        android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="发送"/>

    <Button
        android:id="@+id/btn3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="取消连接"/>

</LinearLayout>

服务端可以使用 TCP Test Tool 小工具进行测试(图为向后台服务器发送十六进制数据):
注:在进行测试时,通过APP发送的应为编辑框中的字符,如果想发送字节流需要通过Java字节数组进行转换。
例如:
定义private byte[ ] msgol = new byte[2];
msgol[0] = (byte) 0x06;
msgol[1] = (byte) 0x01;
图所示为通过字节数组处理后的结果:
在这里插入图片描述

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kevin&Amy

感谢您的鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值