创建一个python服务器,使用socket将数据发送到Android应用程序

创建一个python服务器,使用socket将数据发送到Android应用程序,android,python,sockets,chat,Android,Python,Sockets,Chat,我正在尝试使用python中的socket(我的pc)创建一个简单的聊天服务器程序,以与我的Android客户端代码(我的Android手机)通信 我有一个简单的服务器代码,它接收消息,但它会阻止客户端应用程序,并在我尝试从服务器向客户端发送消息时崩溃 客户端代码基于本教程: 客户端代码: private class ChatClientThread extends Thread { String name; String dstAddress; int dst

我正在尝试使用python中的socket(我的pc)创建一个简单的聊天服务器程序,以与我的Android客户端代码(我的Android手机)通信

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

客户端代码基于本教程:

客户端代码:

    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)
关于如何修复它有什么想法吗?

Java中的和方法在python中没有任何直接的等价物。作为国家的Javadocs:

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

这两个长度字节是按大端顺序排列的。因此,至少,读取此信息的python程序必须首先读取这两个长度的字节以确定后续数据的长度,然后读取大量经过特殊编码的字符数据,最后对其进行解码。基于对所使用的编码的讨论,在python端对其进行解码似乎非常重要,称为“修改的UTF-8”:

此格式与标准UTF-8格式之间的差异如下 以下是:

  • 空字节“\u0000”以2字节格式而不是1字节格式编码, 这样编码的字符串就不会嵌入空值
  • 仅使用1字节、2字节和3字节格式
  • 补充字符以代理项对的形式表示
作为一种替代方法,我认为在java方面会更容易考虑放弃<代码> Read Uf()/Cuff>和 RealEdff()/Case>方法,并用以下的自己的版本替换它们:

public void writeUTF8(字符串s,数据输出)引发IOException{
byte[]encoded=s.getBytes(StandardCharsets.UTF_8);
out.writeInt(编码的长度);
输出。写入(编码);
}
公共字符串readUTF8(DataInput in)引发IOException{
int length=in.readInt();
字节[]编码=新字节[长度];
in.可读(编码);
返回新字符串(编码,StandardCharsets.UTF_8);
}
然后,在python方面,等效代码可以是:

def recvall(袜子,尺寸):
已接收的_块=[]
buf_尺寸=4096
剩余=尺寸
当剩余值大于0时:
接收=存储容量(最小值(剩余,基本尺寸))
如果没有收到:
引发异常(“未接受的EOF”)
已接收\u块。追加(已接收)
剩余-=len(已接收)
返回b“”。加入(收到的\u块)
def读取_utf8(sock):
len_bytes=recvall(sock,4)
长度=结构解包('>i',len_字节)[0]
encoded=recvall(袜子,长度)
返回str(编码,编码='utf-8')
def write_utf8(s:str,sock:socket.socket):
encoded=s.encode(encodeding='utf-8')
sock.sendall(结构包('>i',len(编码)))
sock.sendall(编码)

“它崩溃了…”。怎么用?坠机的痕迹是什么?它在哪一条线上撞车?你有没有做过任何努力来确保你从一边写的东西在另一边被合理地读入?例如,Java的DataInput/DataOutput readUTF()/writeUTF()与普通python socket.send()和socket.recv()不兼容。当我添加以下两行时,服务器代码变得无响应:q=raw\u input()c.send(q)我必须断开连接并重新连接。@JamesKPolk我做了一个log.d,实际上我得到了最多5个字符的字节。这些字节是数字,所以我需要解码接收到的数据。
  q = raw_input()
  c.send(q)