目前我是我的團隊中唯一知道C++語言的人。因此我負責爲我們現有的(可穿戴的)網絡應用程序創建本地tizen服務。Tizen模擬器UDP連接
該服務的主要目的是接收從同一網絡內的系統(即連接到相同接入點)廣播的UDP消息。
我製作了2個簡單的python腳本。第一個按鈕點擊發送廣播消息:
class UDPServer(object):
'''
A simple UDP server with a send method.
'''
def __init__(self):
'''
Initializes the server.
'''
import socket
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
def broadcast_message(self, message):
'''
Sends out a broadcast message.
'''
self.socket.sendto(message, ('<broadcast>', 3333))
class GUI(object):
'''
A simple UI to use the server with.
'''
def __init__(self):
'''
Initializes the simple ui.
'''
import Tkinter
self.root = Tkinter.Tk()
self.root.title("UDP System")
self.button = Tkinter.Button(self.root, text="Action!")
self.button.place(x=0, y=0)
self.button.pack(fill='x')
self.root.update()
def action(self, callback, *args):
'''
Sets the action to be performed when the button's being called.
'''
self.button.configure(command=lambda: callback(*args))
def run(self):
'''
Invokes the message pump of the root widget.
'''
self.root.mainloop()
def main():
'''
Launches the UDP server and its ui.
'''
server = UDPServer()
gui = GUI()
gui.action(server.broadcast_message, "Hello, World!")
gui.run()
if __name__ == '__main__':
main()
,後者接收這些郵件:
class GUI(object):
'''
Simple GUI for the receiver.
'''
def __init__(self):
'''
Initializes the UI.
'''
import Tkinter
self.root = Tkinter.Tk()
self.root.title("UDPReceiver")
self.list = Tkinter.Listbox(self.root)
self.list.pack(fill='x')
def add_message(self, message):
'''
Adds an message to the listbox.
'''
self.list.insert(0, message)
def run(self):
'''
Runs the widgets mainloop.
'''
self.root.mainloop()
class Receiver(object):
'''
Simple UDP receiver.
'''
def __init__(self):
'''
Initializes a simple udp receiver/client.
'''
import socket
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.socket.bind(('', 3333))
def recv(self):
'''
Listens for a message and returns it.
'''
return self.socket.recvfrom(4096)
def main():
'''
Launches the udp receiver and its ui.
'''
gui = GUI()
client = Receiver()
def proc():
'''
A simple fetch and update routine to be run
in a seperate thread.
'''
while gui.root.state() == 'normal':
msg = client.recv()
gui.add_message(msg)
from thread import start_new_thread
start_new_thread(proc,())
gui.run()
if __name__ == '__main__':
main()
顯然,這兩個腳本都正常工作,因爲我能夠收到對方發出的消息腳本(但是,測試它只在同一臺PC上)。
現在我正在嘗試爲本地服務實施「聆聽行爲」。該應用程序似乎工作正常,沒有崩潰。然而,它沒有收到任何東西,雖然下面的代碼似乎罰款:
UDPSocket::UDPSocket()
: socket{0}
{
addrinfo hints{0, };
const char* pHostname = 0;
const char* pPortname = "3333";
hints.ai_family = AF_UNSPEC;
hints.ai_family = SOCK_DGRAM;
hints.ai_protocol = 0;
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
addrinfo* res{nullptr};
int err = ::getaddrinfo(pHostname, pPortname, &hints, &res);
if(0 != err){
throw std::runtime_error{"Failed to get address info."};
}
socket = ::socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if(-1 == socket){
throw std::runtime_error{"Failed to create socket."};
}
int broadcast = 1;
::setsockopt(socket, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
err = ::bind(socket, res->ai_addr, res->ai_addrlen);
if(-1 == err){
throw std::runtime_error{"Failed to bind socket."};
}
freeaddrinfo(res);
}
UDPSocket::~UDPSocket()
{
close(socket);
}
std::string UDPSocket::listen() const{
char buffer[512];
sockaddr_storage src_addr;
socklen_t src_addr_len = sizeof(src_addr);
ssize_t count = ::recvfrom(socket,
buffer,
sizeof(buffer),
0,
(sockaddr*) &src_addr,
&src_addr_len);
if(-1 == count){
throw std::runtime_error{strerror(errno)};
} else if (count == sizeof(buffer)){
// Issue warning
return buffer;
} else{
return buffer;
}
}
應用程序運行良好的模擬器,除了一個事實,即當調用服務攤位「UDPSocket ::聽()」 - 我想這是因爲我處於阻塞模式。它停滯不前,並且從不接收任何東西,無論我多久打一次發送按鈕,都會使用UDP消息氾濫我的本地網絡。
TL; DR 在Tizen模擬器上接收UDP消息需要什麼特殊的配置步驟嗎?
紅利問題: 我想要一種方法來持續注意傳入的UDP消息。 我應該爲服務中的「接收器」啓動一個額外的線程嗎?