创建一个 python 服务器以使用套接字向 Android 应用程序发送数据

2024-03-24

我正在尝试使用 python 中的套接字(我的电脑)创建一个简单的聊天服务器程序来与我的 Android 客户端代码(我的 Android 手机)进行通信。

我有一个简单的服务器代码,它接收消息,但当我尝试从服务器向客户端发送消息时,它会阻止客户端应用程序并崩溃。

客户端代码基于本教程:简单的 Android 聊天应用程序,客户端。 http://android-er.blogspot.ca/2014/08/simple-android-chat-application-client.html

客户端代码:

    private class ChatClientThread extends Thread {

    String name;
    String dstAddress;
    int dstPort;
    
    String msgToSend = "";
    boolean goOut = false;

    ChatClientThread(String name, String address, int port) {
        this.name = name;
        dstAddress = address;
        dstPort = port;
    }

    @Override
    public void run() {
        Socket socket = null;
        DataOutputStream dataOutputStream = null;
        DataInputStream dataInputStream = null;

        try {
            socket = new Socket(dstAddress, dstPort);
            dataOutputStream = new DataOutputStream(
                    socket.getOutputStream());
            dataInputStream = new DataInputStream(socket.getInputStream());
            dataOutputStream.writeUTF(name);
            dataOutputStream.flush();

            while (!goOut) {
                if (dataInputStream.available() > 0) {
                    msgLog += dataInputStream.readUTF();

                    MainActivity.this.runOnUiThread(new Runnable() {

                        @Override
                        public void run() {
                            chatMsg.setText(msgLog);
                        }
                    });
                }
                
                if(!msgToSend.equals("")){
                    dataOutputStream.writeUTF(msgToSend);
                    dataOutputStream.flush();
                    msgToSend = "";
                }
            }

        } catch (UnknownHostException e) {
            e.printStackTrace();
            final String eString = e.toString();
            MainActivity.this.runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, eString, Toast.LENGTH_LONG).show();
                }
                
            });
        } catch (IOException e) {
            e.printStackTrace();
            final String eString = e.toString();
            MainActivity.this.runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, eString, Toast.LENGTH_LONG).show();
                }
                
            });
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            if (dataOutputStream != null) {
                try {
                    dataOutputStream.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            if (dataInputStream != null) {
                try {
                    dataInputStream.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            MainActivity.this.runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    loginPanel.setVisibility(View.VISIBLE);
                    chatPanel.setVisibility(View.GONE);
                }
                
            });
        }

    }
    
    private void sendMsg(String msg){
        msgToSend = msg;
    }
    
    private void disconnect(){
        goOut = true;
    }
}

服务器代码:

import socket

s = socket.socket()
host = "192.168.1.82"
port = 8080

s.bind((host, port))
print host
s.listen(5)
c = None

while True:
   if c is None:
       # Halts
       print '[Waiting for connection...]'
       c, addr = s.accept()
       print 'Got connection from', addr
   else:
       # Halts
       print '[Waiting for response...]'
       print c.recv(1024)

当添加以下两行来发送消息时,它不起作用。

   # Halts
   print '[Waiting for response...]'
   print c.recv(1024)
  q = raw_input()
  c.send(q)

关于如何修复它有什么想法吗?


The DataOutput.writeUTF() https://docs.oracle.com/javase/8/docs/api/java/io/DataOutput.html#writeUTF-java.lang.String- and DataInput.readUTF() https://docs.oracle.com/javase/8/docs/api/java/io/DataInput.html#readUTF--Java 中的方法在 Python 中没有任何直接等效项。正如 Javadoc 中的DataOutput.writeUTF() https://docs.oracle.com/javase/8/docs/api/java/io/DataOutput.html#writeUTF-java.lang.String- state:

将两个字节的长度信息写入输出流,随后 通过字符串中每个字符的修改后的 UTF-8 表示 s。如果 s 为 null,则抛出 NullPointerException。中的每个角色 字符串 s 被转换为一组、两个或三个字节, 取决于角色的价值。

两个长度字节按大端顺序排列。因此,读取此信息的Python程序至少必须首先读取这两个长度字节以确定后续数据的长度,然后读取那么多字节的特殊编码字符数据,最后对其进行解码。根据讨论,在 python 端对其进行解码似乎并不简单here https://docs.oracle.com/javase/8/docs/api/java/io/DataInput.html关于所使用的编码,称为“modified UTF-8”:

该格式与标准UTF-8格式的区别是 下列:

  • 空字节 '\u0000' 以 2 字节格式编码,而不是 1 字节, 以便编码的字符串永远不会嵌入空值。
  • 仅使用 1 字节、2 字节和 3 字节格式。
  • 补充字符以代理对的形式表示。

作为我认为更容易的替代方案,在 Java 方面考虑放弃readUTf() and writeUTF()方法并将其替换为您自己的版本,如下所示:

public void writeUTF8(String s, DataOutput out) throws IOException {
    byte [] encoded = s.getBytes(StandardCharsets.UTF_8);
    out.writeInt(encoded.length);
    out.write(encoded);
}

public String readUTF8(DataInput in) throws IOException {
    int length = in.readInt();
    byte [] encoded = new byte[length];
    in.readFully(encoded);
    return new String(encoded, StandardCharsets.UTF_8);
}

然后,在 python 方面,等效的代码可能是:

def recvall(sock, size):
    received_chunks = []
    buf_size = 4096
    remaining = size
    while remaining > 0:
        received = sock.recv(min(remaining, buf_size))
        if not received:
            raise Exception('unexcepted EOF')
        received_chunks.append(received)
        remaining -= len(received)
    return b''.join(received_chunks)


def read_utf8(sock):
    len_bytes = recvall(sock, 4)
    length = struct.unpack('>i', len_bytes)[0]
    encoded = recvall(sock, length)
    return str(encoded, encoding='utf-8')


def write_utf8(s: str, sock: socket.socket):
    encoded = s.encode(encoding='utf-8')
    sock.sendall(struct.pack('>i', len(encoded)))
    sock.sendall(encoded)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

创建一个 python 服务器以使用套接字向 Android 应用程序发送数据 的相关文章

随机推荐

  • guice 辅助注入 + 多重绑定 + 仿制药

    我试图结合 Guice 的这 3 个功能 注入 多重绑定 泛型 我创建了一个生产项目的原型 所以这里是 首先 这是泛型的一个小层次结构 在生产情况下有 N 个实体的层次结构 public interface Type public clas
  • sqlalchemy:在日期时间列上应用类似 SQL 的 date() 函数

    我想按日期分组并计算结果数id使用 sqlalchemy 不幸的是 我的专栏包含日期信息created datetime是一个日期时间 我想使用像这样的sql函数 group by date created datetime 为了按日期分组
  • 即使应用程序被强制停止,也要重新启动服务,并且即使关闭应用程序后,也要在后台继续运行服务如何?

    我正在尝试在后台运行服务 我的应用程序所做的是 当用户选中复选框时 服务启动 未选中时服务停止 这工作得很好 但问题是 当我从任务管理器关闭应用程序时 它也会停止服务 我想要的是即使在关闭任务管理器后仍保持服务运行 那么停止该服务的唯一方法
  • 类型错误:无法在反应中读取 null 的属性“名称”

    我对 React 和 Redux 很陌生 所以在做了大量研究后我无法轻松解决这个错误 我试图以卡片的形式在单独的页面中显示用户的个人资料 但出现错误 TypeError Cannot read property name of null P
  • 我们如何在 Apache Arrow 中存储哈希表?

    我对 Apache Arrow 很陌生 所以这个问题可能是无知的 Apache Arrow 提供了以标准化内存格式存储原始类型 结构 数组等数据结构的功能 我想知道是否可以使用 Apache Arrow 存储更复杂的数据结构 如哈希表 或平
  • javascript date getYear() 在 IE 和 Firefox 之间返回不同的结果,如何解决这个问题?

    显然 javascript日期对象的方法 getYear 在 IE8 和 Firefox3 6 之间返回不同的结果 我的机器上有这两个 不确定其他浏览器或版本 Date d new Date alert d getYear FF3 6 gt
  • 如何在iis 7.5中使Asp.net网站离线

    我有一个 ASP NET 网站 但我想在我的客户尝试访问该网站时显示 正在维护 页面 有谁知道如何做到这一点 如果您在 NET 4 0 应用程序池 IIS 7 0 或 IIS 7 5 中运行应用程序 或者您的网站配置为 ASP NET 4
  • Angular - 周围的条件 div 容器

    在我的 app component html 中 我想根据当前 url 渲染某些 div 容器 例如 1 如果当前 URL 是authenticate 则呈现以下内容 div div
  • nvm ls-remote 命令结果为“N/A”

    我正在尝试使用 nvm 安装 Node 但是当我输入任何版本时它都不可用 当我打字时nvm ls remote我只是得到 不适用 我可以访问互联网 所以我不知道会发生什么 更新维护 nvm sh 的 LJHarb 的评论 LJHarb 表示
  • 声明 @synthesize 时单下划线和双下划线的区别

    在最近的 Xcode 4 3 项目模板中 一些 synthesze声明为 synthesize window window synthesize managedObjectContext managedObjectContext synth
  • 无法推送到 Gitlab 注册表 | Quarkus - 臂架构建

    我目前正在开发 Quarkus 应用程序 因此需要 CI 管道 容器注册表 由于通过 docker 的容器化不起作用 docker 守护进程 特权模式 我想使用 Jib Quarkus 已经支持它 管道中的命令 mvn clean pack
  • 有没有办法动态配置 nginx(或其他快速反向代理)?

    假设我们有几个相同的节点 它们是某个 n 层服务的应用程序服务器 假设我们使用 Apache ZooKeeper 来保存分布式应用程序的所有配置 另外 我们在此应用程序前面有一个 nginx 作为负载均衡器和反向代理 假设我们执行的命令仅更
  • 使用BIOS int 13h访问不同磁头的扇区

    我的磁盘每磁道有 63 个扇区 根据我的观察 我假设 我想使用 int 13h 读取 16 位引导加载程序上的扇区 例如 如果我想读取扇区号 63 我将执行以下操作 mov dl 0x80 Drive number mov dh 0 Thi
  • 如何在d3中增量绘制网格?

    下面是一个 HTML 文件 它将绘制一个 10x10 的浅灰色和深灰色交替的正方形网格 它填充一个名为的二维数组the grid与 0 或 1 然后填充一个名为的一维数组nodes with x y and color 然后画nodes与
  • JUnitCore 停止

    我想停止 销毁正在运行的 JUnitCore 它的启动方式是 JUnitCore run Request aClass ClassToRun Like pleaseStop 在 RunNotifier 上 有任何想法吗 http junit
  • ajax 请求后重新加载 dojo 小部件

    我是这个主题的新手 我有 div 里面有一些 dojo 小部件 我使用 ajax 重新加载这个 div 但是之后我的 dojo 小部件没有显示 我怎样才能让我的浏览器在ajax请求后再次重新加载小部件 我不想重新加载整个页面 我的ajax视
  • Polymer 2.0:通知并反映到属性

    我是这个框架的新手 希望看到一些有用且简单的通知和反映属性属性的示例 请保持示例简单或为您提供的任何代码添加解释 Notify 可以设置为 True False 假设你有parent element and child element 工作
  • python 的斯坦福大学 nlp

    我想做的就是找到任何给定字符串的情绪 积极 消极 中性 在研究过程中 我遇到了斯坦福 NLP 但遗憾的是它是在 Java 中 关于如何让它适用于 python 有什么想法吗 Use py corenlp https github com s
  • 线程实现(C#)

    您能给我一个使用线程的程序的简单示例吗 我不明白线程及其使用以及何时使用它 谢谢 有一个here http msdn microsoft com en us library aa645740 28VS 71 29 aspx 和一个非常简单的
  • 创建一个 python 服务器以使用套接字向 Android 应用程序发送数据

    我正在尝试使用 python 中的套接字 我的电脑 创建一个简单的聊天服务器程序来与我的 Android 客户端代码 我的 Android 手机 进行通信 我有一个简单的服务器代码 它接收消息 但当我尝试从服务器向客户端发送消息时 它会阻止