Android之okhttp实现socket通讯(非原创)

文章大纲

一、okhttp基础介绍
二、socket通讯代码实战
三、项目源码下载
四、参考文章

一、okhttp基础介绍

https://www.jianshu.com/p/e3291b7808e7

二、socket通讯代码实战

1. 添加依赖和权限

app的build.gradle下添加okhttp依赖

implementation 'com.squareup.okhttp3:okhttp:3.8.1'

AndroidManifest.xml文件添加网络权限

<uses-permission  android:name="android.permission.INTERNET" />

2. 添加布局文件

activity_main.xml文件中代码如下:

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

    <Button
        android:id="@+id/start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="start"
        android:textSize="16sp" />

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/start2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="start2"
        android:textSize="16sp" />

    <TextView
        android:id="@+id/text2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

3. MainActivity逻辑实现

package aidl_customer.com.wj.http_socket;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;

/**
 * okhttp是3.5以后才添加对WebSocket的支持
 */
public class MainActivity extends AppCompatActivity {

    private Button start;
    private TextView text;

    private Button start2;
    private TextView text2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        start = (Button) findViewById(R.id.start);
        text = (TextView) findViewById(R.id.text);

        start2 = (Button) findViewById(R.id.start2);
        text2 = (TextView) findViewById(R.id.text2);

        start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                connect();
            }
        });

        start2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                OkHttpClient  client = new OkHttpClient.Builder()
                        .readTimeout(3, TimeUnit.SECONDS)
                        .build();


                Request request = new Request.Builder()
                        .url("ws://echo.websocket.org")
                        .build();
                WebSocket webSocket = client.newWebSocket(request, new WebSocketListener() {
                    @Override
                    public void onOpen(WebSocket webSocket, Response response) {
                        super.onOpen(webSocket, response);
                    }

                    @Override
                    public void onMessage(WebSocket webSocket, String text) {
                        super.onMessage(webSocket, text);
                    }

                    @Override
                    public void onMessage(WebSocket webSocket, ByteString bytes) {
                        super.onMessage(webSocket, bytes);
                    }

                    @Override
                    public void onClosing(WebSocket webSocket, int code, String reason) {
                        super.onClosing(webSocket, code, reason);
                    }

                    @Override
                    public void onClosed(WebSocket webSocket, int code, String reason) {
                        super.onClosed(webSocket, code, reason);
                    }

                    @Override
                    public void onFailure(WebSocket webSocket, Throwable t, Response response) {
                        super.onFailure(webSocket, t, response);
                    }
                });
            }
        });
    }

    /**
     *WebSocket官网就提供了相应url可以测试
     */
    private void connect() {

        //建立连接
        EchoWebSocketListener listener = new EchoWebSocketListener();
        Request request = new Request.Builder()
                .url("ws://echo.websocket.org")
                .build();
        OkHttpClient client = new OkHttpClient();
        client.newWebSocket(request, listener);

        client.dispatcher().executorService().shutdown();
    }

    /**
     * 重写了WebSocketListener中的几个方法,这几个方法很好理解,是用来异步回调的,
     * 这里简单说一下:onOpen当WebSocket和远程建立连接时回调;两个onMessage就是接收到消息时回调,
     * 只是消息内容的类型不同;onClosing是当远程端暗示没有数据交互时回调(即此时准备关闭,但连接还没有关闭);
     * onClosed就是当连接已经释放的时候被回调;onFailure当然是失败时被回调(包括连接失败,发送失败等)。
     *
     * send用来发送消息;close用来关闭连接
     */
    private final class EchoWebSocketListener extends WebSocketListener {

        @Override
        public void onOpen(WebSocket webSocket, Response response) {

            webSocket.send("hello world");
            webSocket.send("welcome");
            webSocket.send(ByteString.decodeHex("adef"));
            webSocket.close(1000, "再见");
        }

        @Override
        public void onMessage(WebSocket webSocket, String text) {
            output("onMessage: " + text);
        }

        @Override
        public void onMessage(WebSocket webSocket, ByteString bytes) {
            output("onMessage byteString: " + bytes);
        }

        @Override
        public void onClosing(WebSocket webSocket, int code, String reason) {
            webSocket.close(1000, null);
            output("onClosing: " + code + "/" + reason);
        }

        @Override
        public void onClosed(WebSocket webSocket, int code, String reason) {
            output("onClosed: " + code + "/" + reason);
        }

        @Override
        public void onFailure(WebSocket webSocket, Throwable t, Response response) {
            output("onFailure: " + t.getMessage());
        }
    }

    private void output(final String content) {

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                text.setText(text.getText().toString() + content + "\n");
            }
        });
    }
}

温馨提示:
(1)EchoWebSocketListener继承OkHttp中的抽象类WebSocketListener,重写了几个方法,是用来异步回调的,这里简单说一下:onOpen当WebSocket和远程建立连接时回调;两个onMessage就是接收到消息时回调,只是消息内容的类型不同;onClosing是当远程端暗示没有数据交互时回调(即此时准备关闭,但连接还没有关闭);onClosed就是当连接已经释放的时候被回调;onFailure当然是失败时被回调(包括连接失败,发送失败等)。
(2)send用来发送消息;close用来关闭连接
(3)WebSocket官网就提供了相应url可以测试,测试地址为:ws://echo.websocket.org
(4)关闭连接方式,OkHttp提供两个方法来关闭连接:
  1)close webSocket.close(0, “bye”);请求服务器优雅地关闭连接然后等待确认。在关闭之前,所有已经在队列中的消息将被传送完毕。 既然涉及到交互,那么socket可能不会立即关闭。如果初始化和关闭连接是和Activity的生命周期绑定的(比如onPause/onResume),有一些消息可能是在close被调用之后接收到,所以这需要小心去处理。
  2)cancel;cancel更加残忍:它会丢弃所有已经在队列中的消息然后残忍地关闭socket。这样也有优点:不必等待家政(housekeeping)和已在队列中消息的传送。然而,选择cancel还是close取决于使用场景。

4. 项目运行与访问

安装apk后,运行主页面如下:

点击START按钮,出现以下结果

三、项目源码下载

链接:https://pan.baidu.com/s/1t8OmZy8WLZr2aKI8S2XcwQ
提取码:jwzi

四、参考文章

  1. https://blog.csdn.net/xlh1191860939/article/details/75452342/
  2. https://blog.csdn.net/xlh1191860939/article/details/75452513
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容

  • 随着web技术的发展,使用场景和需求也越来越复杂,客户端不再满足于简单的请求得到状态的需求。实时通讯越来越多应用于...
    什么都不会的程序员阅读 1,877评论 0 4
  • 6.1 公钥密钥加密原理 6.1.1 基础知识 密钥:一般就是一个字符串或数字,在加密或者解密时传递给加密/解密算...
    AndroidMaster阅读 4,009评论 1 8
  • 网络编程 1. 概论 建立连接:通过IP或者域名来连接两台设备,通过端口号找到对应的通信程序 通信协议:要传输的数...
    陵无山阅读 3,937评论 0 12
  • 文/风往北云向南 加西亚·马尔克斯 最近总是听别人提起加西亚·马尔克斯这本书。魔幻现实主义作品,据说莫言写《丰乳肥...
    胡诌白扯阅读 805评论 2 11
  • 又到了给母亲拿药的时候了,因为前几次稍微晚了一点,到医院检查拿药就需要花费一天的时间,习惯早起的母亲商量,早上六点...
    晓艳_f118阅读 326评论 3 4