Android studio—socketIO库return与emit的使用

文章目录


Socket.IO 是一个流行的实时通信库,支持 WebSocket 和其他回退机制(如长轮询),能够在客户端和服务器之间实现低延迟的双向通信。

一、Socket.IO库简单使用说明

1. 后端 Flask + Flask-SocketIO

首先,确保你的 Flask 后端已经安装了 Flask-SocketIO。你可以通过以下命令安装:

bash 复制代码
pip install Flask Flask-SocketIO

以下是一个简单的 Flask 后端示例代码:

python 复制代码
from flask import Flask
from flask_socketio import SocketIO, emit

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_secret_key'
socketio = SocketIO(app)

@app.route('/')
def index():
    return "Hello, World!"

@socketio.on('message')
def handle_message(msg):
    print('Received message: ' + msg)
    emit('response', 'Echo: ' + msg, broadcast=True)

if __name__ == '__main__':
    socketio.run(app, debug=True)
2. Android 客户端集成 Socket.IO

在 Android Studio 中,你需要添加 Socket.IO 的依赖。在 build.gradle 文件中添加以下内容:

gradle 复制代码
dependencies {
    implementation 'io.socket:socket.io-client:1.4.0'
}

确保你的应用有网络权限。在 AndroidManifest.xml 文件中添加以下内容:

xml 复制代码
<uses-permission android:name="android.permission.INTERNET" />

以下是一个简单的 Android 客户端示例:

java 复制代码
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;

public class MainActivity extends AppCompatActivity {
    private Socket socket;

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

        try {
            socket = IO.socket("http://yourserver.com/socket.io");
            socket.connect();

            socket.on("response", new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            TextView messagesView = findViewById(R.id.messagesView);
                            messagesView.append((String) args[0] + "\n");
                        }
                    });
                }
            });

            Button sendButton = findViewById(R.id.sendButton);
            sendButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    EditText messageInput = findViewById(R.id.messageInput);
                    String message = messageInput.getText().toString();
                    if (!message.isEmpty()) {
                        socket.emit("message", message);
                        messageInput.setText("");
                    }
                }
            });

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        socket.disconnect();
    }
}
3. 布局文件

res/layout/activity_main.xml 中定义一个简单的布局:

xml 复制代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <EditText
        android:id="@+id/messageInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Type a message" />

    <Button
        android:id="@+id/sendButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send" />

    <TextView
        android:id="@+id/messagesView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Messages will appear here"
        android:textSize="16sp" />

</LinearLayout>

socket.onsocket.emit

特性 socket.on socket.emit
功能 监听来自服务器的事件 向服务器发送事件
方向 从服务器到客户端 从客户端到服务器
回调 注册回调函数以处理接收到的事件 可选地注册回调函数以接收服务器的响应
使用场景 接收服务器推送的消息,如通知、广播等 发送请求到服务器,如提交数据、请求信息等
注意事项
  1. 服务器地址:确保在 Android 客户端中使用的服务器地址与 Flask 后端的地址一致。
  2. 网络权限 :确保在 AndroidManifest.xml 中添加了网络权限。
  3. 线程安全 :在回调函数中更新 UI 时,确保使用 runOnUiThread

二、接受服务器消息的二种方法

  • emit
    • 后端 :使用 emit 发送事件和数据。
    • 客户端 :通过 socket.on 监听事件并接收数据。
  • return
    • 后端 :在事件处理函数中使用 return 发送响应。
    • 客户端 :通过 emit 方法的回调函数接收响应。
1. 客户端接收通过 emit 发送的消息

当后端使用 emit 发送消息时,客户端可以通过 socket.on 监听对应的事件来接收消息。

功能
  • 显式发送事件emit 可以发送自定义事件,并携带数据。
  • 广播或单播:可以指定发送给所有客户端,或者特定的客户端。
使用场景
  • 广播消息:向所有连接的客户端发送消息。
  • 单播消息:向特定的客户端发送消息。
  • 复杂交互:需要发送多个事件或不同类型的数据时。
后端代码(Flask-SocketIO)
python 复制代码
from flask import Flask
from flask_socketio import SocketIO, emit

app = Flask(__name__)
socketio = SocketIO(app)

@socketio.on('client_message')
def handle_client_message(data):
    print("Received message:", data)
    emit('server_message', 'Hello from Server!')  # 使用 emit 发送消息

if __name__ == '__main__':
    socketio.run(app, host='0.0.0.0', port=5000)
客户端代码(Android Studio,Java)
java 复制代码
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;

public class MainActivity extends AppCompatActivity {
    private Socket mSocket;

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

        try {
            mSocket = IO.socket("http://your-server-address:5000");
            mSocket.connect();

            // 监听服务器通过 emit 发送的消息
            mSocket.on("server_message", new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    String message = (String) args[0];
                    runOnUiThread(() -> {
                        Toast.makeText(MainActivity.this, "Received via emit: " + message, Toast.LENGTH_SHORT).show();
                    });
                }
            });

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mSocket.disconnect();
        mSocket.off("server_message");
    }
}
2. 客户端接收通过 return 发送的响应

当后端使用 return 发送响应时,客户端可以通过 emit 方法的回调函数接收响应。

功能
  • 返回响应:直接返回一个值或字符串。
  • 简单交互:适用于简单的场景,客户端不需要复杂的消息交互。
使用场景
  • 简单响应:客户端只需要一个简单的响应,例如确认消息已接收。
  • 快速反馈:快速返回一个结果,不需要额外的事件处理。
后端代码(Flask-SocketIO)
python 复制代码
from flask import Flask
from flask_socketio import SocketIO

app = Flask(__name__)
socketio = SocketIO(app)

@socketio.on('client_message')
def handle_client_message(data):
    print("Received message:", data)
    return 'Server received your message!'  # 使用 return 发送响应

if __name__ == '__main__':
    socketio.run(app, host='0.0.0.0', port=5000)
客户端代码(Android Studio,Java)
java 复制代码
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;

public class MainActivity extends AppCompatActivity {
    private Socket mSocket;

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

        try {
            mSocket = IO.socket("http://your-server-address:5000");
            mSocket.connect();

            // 发送消息并接收通过 return 发送的响应
            mSocket.emit("client_message", "Hello from Android!", new Emitter.Ack() {
                @Override
                public void call(Object... args) {
                    if (args.length > 0) {
                        String response = (String) args[0];
                        runOnUiThread(() -> {
                            Toast.makeText(MainActivity.this, "Received via return: " + response, Toast.LENGTH_SHORT).show();
                        });
                    }
                }
            });

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mSocket.disconnect();
    }
}
4. 二者的区别
特性 emit return
功能 显式发送事件,携带数据 直接返回响应
方向 从服务器到客户端 从服务器到客户端
使用场景 广播或单播消息,复杂交互 简单响应,快速反馈
示例 emit('server_message', 'Hello from Server!') return 'Server received your message!'
  • 如果你需要向客户端发送复杂的事件或广播消息,使用 emit
  • 如果客户端只需要一个简单的响应,使用 return

拓展:room与namespace

在 Flask-SocketIO 中,命名空间(Namespace)和房间(Rooms)是两个非常重要的功能,它们可以更好地组织和管理实时通信。

命名空间(Namespace)

命名空间允许在同一个 Socket.IO 服务器上创建多个独立的通信通道。每个命名空间都可以有自己的事件和逻辑,互不干扰。这在大型应用中非常有用,可以将不同的功能模块分开,例如聊天功能和通知功能。

功能示例
python 复制代码
from flask_socketio import emit

@socketio.on('message', namespace='/chat')
def handle_chat_message(msg):
    emit('message', msg, broadcast=True, namespace='/chat')

@socketio.on('notification', namespace='/notifications')
def handle_notification(msg):
    emit('notification', msg, broadcast=True, namespace='/notifications')

在上面的代码中,/chat/notifications 是两个不同的命名空间,分别用于处理聊天消息和通知。

房间(Rooms)

房间是命名空间的进一步细分,允许将用户分组,以便向特定的用户组发送消息。这在聊天室、多人游戏等场景中非常有用。

功能示例
python 复制代码
from flask_socketio import join_room, leave_room

@socketio.on('join')
def on_join(data):
    username = data['username']
    room = data['room']
    join_room(room)
    send(username + ' has entered the room.', to=room)

@socketio.on('leave')
def on_leave(data):
    username = data['username']
    room = data['room']
    leave_room(room)
    send(username + ' has left the room.', to=room)

在上面的代码中,join_roomleave_room 函数用于管理用户加入和离开房间。send 函数的 to 参数用于指定消息发送到的房间。

总结
  • 命名空间:用于创建独立的通信通道,适合将不同的功能模块分开。
  • 房间:用于将用户分组,适合向特定用户组发送消息。

通过合理使用命名空间和房间,可以构建更加模块化和高效的实时通信应用。

拓展:

room功能实现用户之间消息的发送

相关推荐
新时代的弩力3 分钟前
CSRF 和 XSS 攻击分析与防范
网络
荔枝吻22 分钟前
【抽丝剥茧知识讲解】引入mybtis-plus后,mapper实现方式
java·sql·mybatis
在未来等你27 分钟前
互联网大厂Java求职面试:构建高并发直播平台的架构设计与优化
java·spring boot·微服务·kubernetes·高并发·分布式系统·直播平台
轮到我狗叫了1 小时前
力扣.1471数组的k个最强值,力扣.1471数组的k个最强值力扣1576.替换所有的问号力扣1419.数青蛙编辑力扣300.最长递增子序列
java·数据结构·算法
秋野酱1 小时前
基于SpringBoot的家政服务系统设计与实现(源码+文档+部署讲解)
java·spring boot·后端
EQ-雪梨蛋花汤1 小时前
【Part 2安卓原生360°VR播放器开发实战】第四节|安卓VR播放器性能优化与设备适配
android·性能优化·vr
趁你还年轻_1 小时前
常用的Java工具库
java
不再幻想,脚踏实地1 小时前
Spring Boot 日志
java·spring boot·后端
Think Spatial 空间思维1 小时前
【HTTPS基础概念与原理】SSL/TLS协议演进史:从SSLv3到TLS 1.3
网络协议·https·ssl
是大强1 小时前
编译OpenSSL时报错,Can‘t locate IPC/Cmd.pm in @INC perl环境
网络·网络协议·ssl