【问题标题】:Django Channels dont sent message to Android AppDjango Channels 不向 Android App 发送消息
【发布时间】:2023-03-17 20:34:01
【问题描述】:

我想将https://channels.readthedocs.io/en/latest/tutorial/part_2.html 的官方 django 频道教程应用到一个简单的 android 应用程序中。

https://medium.com/@ssaurel/learn-to-use-websockets-on-android-with-okhttp-ba5f00aea988,我找到了一个简单的项目,但它使用http://www.websocket.org/echo.html 提供的Echo WebSocket 服务器。

我复制粘贴了同一个项目,但使用 django 通道将 Echo WebSocket 服务器替换为我自己的 websocket 服务器。

代码如下:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private Button start;
    private TextView output;
    private OkHttpClient client;



    private final class EchoWebSocketListener extends WebSocketListener {
        private static final int NORMAL_CLOSURE_STATUS = 1000;

        @Override
        public void onOpen(WebSocket webSocket, Response response) {
            Log.d(TAG, "onOpen() is called.");
            JSONObject obj = new JSONObject();
            JSONObject obj2 = new JSONObject();
            try {
                obj.put("message" , "Hello");
                obj2.put("message", "Goodbye!");
            } catch (JSONException e) {
                e.printStackTrace();
            }

            webSocket.send(obj.toString());

            //webSocket.send("What's up ?");
            //webSocket.send(ByteString.decodeHex("deadbeef"));
            webSocket.close(NORMAL_CLOSURE_STATUS, obj2.toString());
        }

        @Override
        public void onMessage(WebSocket webSocket, String text) {
            Log.d(TAG, "onMessage() for String is called.");
            output("Receiving : " + text);
        }

        @Override
        public void onMessage(WebSocket webSocket, ByteString bytes) {
            Log.d(TAG, "onMessage() for ByteString is called.");
            output("Receiving bytes : " + bytes.hex());
        }

        @Override
        public void onClosing(WebSocket webSocket, int code, String reason) {
            Log.d(TAG, "onClosing() is called.");
            webSocket.close(NORMAL_CLOSURE_STATUS, null);
            output("Closing : " + code + " / " + reason);
        }

        @Override
        public void onFailure(WebSocket webSocket, Throwable t, Response response) {
            Log.d(TAG, "onFailure() is called.");
            output("Error : " + t.getMessage());
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        start = (Button) findViewById(R.id.start);
        output = (TextView) findViewById(R.id.output);
        client = new OkHttpClient();
        start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                start();
            }
        });
    }

    void start() {
        Request request = new Request.Builder().url("ws://192.168.122.1:8080/ws/chat/lobby/").build();
        EchoWebSocketListener listener = new EchoWebSocketListener();
        WebSocket ws = client.newWebSocket(request, listener);
        client.dispatcher().executorService().shutdown();
    }
    private void output(final String txt) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                output.setText(output.getText().toString() + "\n\n" + txt);
            }
        });
    }
}

要向/从服务器发送和接收消息,他们使用 okhttp3 库中的 WebSocketListener。

我的consumers.py 文件与 Django 频道教程中的相同。更具体地说,我使用了相同的设置。 尽管如此,为了在同一页面上,我发布了我的 consumers.py 文件的样子:

from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
import json

class SignallingConsumer(WebsocketConsumer):
    def connect(self):
        print("connect() is called.")
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        self.room_group_name = 'chat_%s' % self.room_name

        # Join room group
        async_to_sync(self.channel_layer.group_add)(
            self.room_group_name,
            self.channel_name
        )

        self.accept()

    def disconnect(self, close_code):
        print("disconnect() is called.")

        # Leave room group
        async_to_sync(self.channel_layer.group_discard)(
            self.room_group_name,
            self.channel_name
        )

    # Receive message from WebSocket
    def receive(self, text_data):
        print("receive() is called with " + text_data)
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        print("message contains: " + message)

        # Send message to room group
        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': message
            }
        )

     # Receive message from room group
    def chat_message(self, event):
        print("the message from the event is: " + event['message'])
        message = event['message']

        # Send message to WebSocket
        self.send(text_data=json.dumps({
            'message': message
        }))

我添加了一些打印内容以更好地了解幕后情况,并更改了消费者的名称,因为我想稍后在了解基础知识后将其用作另一个项目的信号服务器。

在控制台上,我得到以下信息:

System check identified no issues (0 silenced).
July 25, 2019 - 10:34:24
Django version 2.2.3, using settings 'signalingserver.settings'
Starting ASGI/Channels version 2.2.0 development server at http://192.168.122.1:8080/
Quit the server with CONTROL-C.
WebSocket HANDSHAKING /ws/chat/lobby/ [192.168.122.1:54194]
connect() is called.
WebSocket CONNECT /ws/chat/lobby/ [192.168.122.1:54194]
receive() is called with {"message":"Hello"}
message contains: Hello
WebSocket DISCONNECT /ws/chat/lobby/ [192.168.122.1:54194]
the message from the event is: Hello
disconnect() is called.

我的 LogCat 输出如下:

07-25 12:35:22.754 5297-5319/com.celik.abdullah.simplewebsocketproject D/MainActivity: onOpen() is called.
07-25 12:35:22.810 5297-5319/com.celik.abdullah.simplewebsocketproject D/MainActivity: onClosing() is called.

从这些输出中,我假设连接和发送部分正在运行。但是从 websocket 服务器接收数据不起作用,因为我的客户端(android 应用程序)上的 onMessage() 没有被调用。

如何解决?

提前谢谢你。

【问题讨论】:

    标签: python android django websocket django-channels


    【解决方案1】:

    如果其他人看到这一点,问题是因为您在有机会从服务器接收任何返回之前关闭了 onOpen 方法中的 Web 套接字。您应该删除该行:

    webSocket.close(NORMAL_CLOSURE_STATUS, obj2.toString());
    

    当您不再使用网络套接字连接时,稍后调用 close。

    其他一切看起来都很棒,并且按原样工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-09
      • 2018-07-11
      • 2018-07-29
      • 2020-05-13
      • 2017-01-12
      • 2019-08-15
      • 1970-01-01
      • 2019-08-06
      相关资源
      最近更新 更多