android - 无法从 Android 模拟器客户端中的 python 服务器接收数据
问题描述
我正在尝试编写一个基于python(套接字)的服务器和一个Android客户端,但是在从服务器向客户端发送数据时,客户端没有收到任何数据。服务器从客户端接收数据。
我认为问题可能出在模拟器上,而不是服务器上,因为我确实建立了连接,并且来自服务器的消息可能被模拟器的防火墙阻止。这是代码:
客户:
public class MainActivity extends AppCompatActivity {
Thread Thread1 = null;
EditText etIP, etPort;
TextView tvMessages;
EditText etMessage;
Button btnSend;
String SERVER_IP;
int SERVER_PORT;
Boolean done = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etIP = findViewById(R.id.etIP);
etPort = findViewById(R.id.etPort);
tvMessages = findViewById(R.id.tvMessages);
etMessage = findViewById(R.id.etMessage);
btnSend = findViewById(R.id.btnSend);
Button btnConnect = findViewById(R.id.btnConnect);
btnConnect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
done = false;
tvMessages.setText("");
SERVER_IP = etIP.getText().toString().trim();
SERVER_PORT = Integer.parseInt(etPort.getText().toString().trim());
Thread1 = new Thread(new Thread1());
Thread1.start();
}
});
btnSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String message = etMessage.getText().toString().trim();
if (!message.isEmpty()) {
if(! done) {
String android_id= Settings.Secure.getString(MainActivity.this.getContentResolver(),
Settings.Secure.ANDROID_ID);
new Thread(new Thread3(android_id)).start();
done = true;
}
new Thread(new Thread3(message)).start();
}
}
});
}
private PrintWriter output;
private BufferedReader input;
class Thread1 implements Runnable {
public void run() {
Socket socket;
try {
socket = new Socket(SERVER_IP, SERVER_PORT);
output = new PrintWriter(socket.getOutputStream());
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
runOnUiThread(new Runnable() {
@Override
public void run() {
tvMessages.setText("Connected\n");
}
});
new Thread(new Thread2()).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Thread2 implements Runnable {
@Override
public void run() {
while (true) {
try {
final String message = input.readLine();
if (message != null) {
runOnUiThread(new Runnable() {
@Override
public void run() {
tvMessages.append("server: " + message + "\n");
}
});
} else {
Thread1 = new Thread(new Thread1());
Thread1.start();
return;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class Thread3 implements Runnable {
private String message;
Thread3(String message) {
this.message = message;
}
@Override
public void run() {
output.write(message);
output.flush();
runOnUiThread(new Runnable() {
@Override
public void run() {
tvMessages.append("client: " + message + "\n");
etMessage.setText("");
}
});
}
}
}
服务器:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
谢谢
解决方案
这种单向行为client -> server
可以正常工作,server -> client
但不能正常工作,这是由于模拟器是 NAT 版的,并且很可能您必须设置一个规则来将入站流量(来自 localhost 端口)转发到模拟器的本地端口.
更多信息和示例在这里。
推荐阅读
- odoo - 我如何在odoo 10中获得金额
- python - 将 Pandas 数据帧从本地机器上传到 Google Cloud 存储桶
- php - 将 DateTime 字符串转换为 DateTime 对象,返回布尔值而不是对象
- machine-learning - 训练集中与测试集中不同的攻击类型(标签)
- javascript - 加载 React 应用程序时如何设置 firebase auth onAuthStateChanged() 监听器运行?
- xml - XSLT 正在为每一行创建单独的表。我如何把它们变成一张桌子?
- ios - NSTextAttachment() 额外属性
- sql - PostgreSQL - 生成每小时列表
- macos - Embedded Postgres 在 Mac OS 上无法获取进程 PID
- ruby - 如何解决 Rubocop 错误 'Favor `format` over `String#%`'