创建一个python服务器以使用套接字将数据发送到Android应用 [英] Create a python server to send data to Android app using socket

查看:66
本文介绍了创建一个python服务器以使用套接字将数据发送到Android应用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to create a simple chat server program using socket in python ( my pc ) to communicate with my Android client code ( my Android phone ) .

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

I have a simple server code which receives messages but it blocks the client app and crashes when I try to send messages from server to client.

客户端代码基于本教程:简单的Android聊天应用程序,客户端。

The client code is based on this tutorial: Simple Android Chat Application, client side.

客户端代码:

    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)

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

When add following two lines to send messages then it doesn't work.

   # Halts
   print '[Waiting for response...]'
   print c.recv(1024)



  q = raw_input()
  c.send(q)


关于如何解决它的任何想法?

Any ideas on how to fix it?

推荐答案

DataOutput.writeUTF() DataInput.readUTF() 方法在python中没有任何直接等效项。作为 DataOutput.writeUTF() 状态:

The DataOutput.writeUTF() and DataInput.readUTF() methods in Java do not have any direct equivalents in python. As the Javadocs for DataOutput.writeUTF() state:


写入两个字节长度信息到输出流,在
之后是字符串
中每个字符的修改后的UTF-8表示形式。如果s为null,则抛出NullPointerException。
中的每个字符s都将转换为一个,两个或三个字节的组,
取决于字符的值。

Writes two bytes of length information to the output stream, followed by the modified UTF-8 representation of every character in the string s. If s is null, a NullPointerException is thrown. Each character in the string s is converted to a group of one, two, or three bytes, depending on the value of the character.

两个长度字节按大端顺序排列。因此,至少,读入此信息的python程序必须首先读入这两个长度的字节以确定后续数据的长度,然后读入那么多字节的特殊编码的字符数据,最后对其进行解码。根据讨论在此使用编码,称为修改的UTF-8:

The two length bytes are in big-endian order. Thus, at a minimum, a python program reading in this information must first read in those two length bytes to determine the length of the subsequent data, then read in that many bytes of specially-encoded character data, and finally decode it. Decoding it on the python side appears to be non-trivial based on the discussion here on the encoding used, called 'modified UTF-8':


标准的UTF-8格式为
以下:

The differences between this format and the standard UTF-8 format are the following:


  • 空字节Theu0000'编码为2字节格式而不是1字节
    ,这样编码后的字符串就永远不会嵌入空值。

  • 仅使用1字节,2字节和3字节格式。

  • 补充字符以代理对的形式表示

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

As an alternative that I think would be much easier, on the Java side consider abandoning the readUTf() and writeUTF() methods and replacing them with your own versions like the following:

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端,等效代码可以是:

And then, on the python side, the equivalent code could be:

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)

这篇关于创建一个python服务器以使用套接字将数据发送到Android应用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆