问题描述
我正在尝试使用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.
客户端代码基于本教程:
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?
推荐答案
和方法在python中没有任何直接等效项。作为状态:
The DataOutput.writeUTF()
and DataInput.readUTF()
methods in Java do not have any direct equivalents in python. As the Javadocs for DataOutput.writeUTF()
state:
两个长度字节按大端顺序排列。因此,至少,读入此信息的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':
- 空字节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应用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!