没有答案的相关问题Using DatagramSocket and python socket with devices connected to hotspot
我的目标是实现类似syncthing的东西,这样我就可以在本地网络上通过设备传输文件。(它是双向的,即Android到PC、PC到Android、PC到PC、Android到Android)
(我的设置是一台笔记本电脑和一台安卓10设备,我用它作为热点,在笔记本电脑中访问互联网)
我一直在尝试使用jmdns
实现网络设备发现,只有当两个设备连接到同一个WIFI时,Jmdns才能够发现本地服务,但当将其用作热点时,它在Android设备上不起作用
我最终能够通过使用Android NSD使它工作,并且它能够在作为热点使用时发现我的pc。在这里,我运行了一个简单的zeroconf python脚本,宣布服务器使用os分配的端口
pip install zeroconf==0.25.0 ifaddr==0.1.6
服务器代码
以下代码将允许PC到PC的消息传递,以便可以完成文件下载。这也允许Android NSD发现该设备
import random
from contextlib import closing
from socket import *
from threading import Thread
from typing import List
import ifaddr
from zeroconf import (ServiceBrowser, ServiceInfo, ServiceListener, Zeroconf,
ZeroconfServiceTypes)
class MyListener:
def remove_service(self, zeroconf, type, name):
print("Service {} of type {} removed".format(name, type))
def add_service(self, zeroconf, type, name):
info = zeroconf.get_service_info(type, name)
print("Service %s added, service info: %s" % (name, info))
# https://stackoverflow.com/a/51596612/8608146
print("Address", inet_ntoa(info.address), info.port)
Thread(target=client_handler, args=(info,)).start()
def client_handler(info: ServiceInfo):
with closing(socket(AF_INET, SOCK_DGRAM)) as s:
print(info.address, info.port)
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
s.bind(('', info.port))
while True:
print("Waiting..", s.getsockname())
m = s.recvfrom(1024)
print(m)
# https://stackoverflow.com/a/45690594/8608146
def find_free_port():
with closing(socket(AF_INET, SOCK_STREAM)) as s:
s.bind(('', 0))
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
return s.getsockname()[1]
# https://github.com/p-sanches/somabits/blob/d581abaab6f045d65a774a78fbb43e232cf6f8da/somoserver/SomoServer/ZeroConf.py#L42
def get_all_addresses() -> List[str]:
return list(set(
addr.ip
for iface in ifaddr.get_adapters()
for addr in iface.ips
# Host only netmask 255.255.255.255
if addr.is_IPv4 and addr.network_prefix != 32
))
def get_local_ip(starts_with="192"):
list_ip = get_all_addresses()
local_ip = [i for i in list_ip if i.startswith(starts_with)]
return local_ip[0]
print(get_all_addresses())
print(get_local_ip())
print(gethostname())
print(gethostbyname(gethostname()))
zeroconf = Zeroconf()
send_port = find_free_port()
local_ip = get_local_ip()
# assign a random name to this service
name = "pc-" + str(random.randint(0, 100))
# register a service
zeroconf.register_service(ServiceInfo(
"_coolapp._udp.local.",
"{}._coolapp._udp.local.".format(name),
inet_aton(local_ip), send_port, 0, 0,
# this is the txt record
properties={"data": "device"}
))
listener = MyListener()
browser = ServiceBrowser(zeroconf, "_coolapp._udp.local.", listener)
try:
std_response = ''
s = socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
while std_response != 'q':
std_response = input("Press q to exit...\n\n")
# print(x)
s.sendto(std_response.encode('utf8'), ('255.255.255.255', send_port))
finally:
zeroconf.close()
我在应用程序中实现了安卓到安卓的消息传递,当两台设备都连接到同一个网络(甚至其中一台是热点)时,它就能工作
现在我一直在尝试从python服务器访问我的Android设备IP,从Android应用程序访问我的笔记本电脑
zeroconf连接实例在Android端有host
字段,即PC的IP和port
。以及python服务器端的address
和port
因此,我在Android应用程序中打开地址host:port
(PC或其他Android设备的主机和端口)的套接字,并在python服务器中从Android应用程序或其他PC的address:port
接收的zeroconf连接的IP上打开套接字。并尝试从Android端读取/写入套接字
它现在只适用于Android到Android和PC到PC的消息传递。但是从pc到Android都拒绝连接。(提醒一下,我正在使用Android设备的热点连接)
Android代码位于in this github repository
代码的套接字部分是
// NSD stuff gives address and port
...
//
// to receive messages from other devices
private inner class ReceivingThread : Runnable {
override fun run() {
...
val s = Socket(address, port)
// The error is here in the next line
// which is simply a timeout Exception
val inputStream = BufferedInputStream(s.getInputStream())
try {
while (!Thread.currentThread().isInterrupted && !s.isClosed) {
...
Log.d(TAG, "[Client RT] receive: $message")
}
} catch (e: Exception) {
Log.d(TAG, "[Client RT] run: something went wrong ${this@Client}", e)
}
}
}
private inner class SendingThread(private val message: String) : Runnable {
override fun run() {
val s = socket ?: return
val outputStream = BufferedOutputStream(s.getOutputStream() ?: return)
Log.d(TAG, "run: outputStream = $outputStream")
try {
outputStream.write(message)
outputStream.flush()
...
Log.d(TAG, "[Client ST] send: $message")
} catch (e: Exception) {
Log.d(TAG, "[Client ST] run: something went wrong $this", e)
}
}
}
从Android应用程序向服务器发送内容时,我的错误是
java.net.ConnectException: failed to connect to /192.168.56.1 (port 51914) from /:: (port 39748): connect failed: ETIMEDOUT (Connection timed out)
尝试连接到服务器中的客户端时
Traceback (most recent call last):
File "C:\Users\Rithvij\AppData\Local\Programs\Python\Python38\lib\threading.py", line 932, in _bootstrap_inner
self.run()
File "C:\Users\Rithvij\AppData\Local\Programs\Python\Python38\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "ano.py", line 65, in client_handler
s.bind((inet_ntoa(info.address), info.port))
OSError: [WinError 10049] The requested address is not valid in its context
在我的电脑上
λ ipconfig.exe | grep IPv4
IPv4 Address. . . . . . . . . . . : 192.168.56.1
IPv4 Address. . . . . . . . . . . : 192.168.99.1
IPv4 Address. . . . . . . . . . . : 192.168.43.159
IPv4 Address. . . . . . . . . . . : 192.168.137.1
在我的Android设备(Termux)上
$ ifconfig | grep inet
Warning: cannot open /proc/net/dev (Permission denied). Limited output.
inet 127.0.0.1 netmask 255.0.0.0
inet 10.83.151.210 netmask 255.255.255.252
inet 25.135.14.145 netmask 255.255.255.252
inet 192.168.43.1 netmask 255.255.255.0 broadcast 192.168.43.255
IP要么无法访问,要么我什么都不知道
目前没有回答
相关问题 更多 >
编程相关推荐