简体   繁体   English

Tizen仿真器UDP连接

[英]Tizen Emulator UDP Connection

currently I am the only guy in my team, who knows the C++ language. 目前,我是团队中唯一了解C ++语言的人。 Therefore I got charged with the task to create a native tizen service for our already existing (wearable) web app. 因此,我承担了为现有(可穿戴)网络应用创建本地tizen服务的任务。

The main purpose of the service is to receive UDP message, which are being broadcasted from a system within the same network (ie connected to same access point). 该服务的主要目的是接收UDP消息,该消息正在从同一网络(即,连接到同一接入点)中的系统广播。

I've made 2 simple python scripts. 我已经制作了2个简单的python脚本。 The first one sends broadcast messages on button clicks: 第一个在单击按钮时发送广播消息:

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()

and the latter receives those messages: 后者收到这些消息:

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()

Apparently both scripts are working correctly, since I am able to receive the messages issued by the other script (however, tested it only on the same PC.) 显然,两个脚本都能正常工作,因为我能够接收其他脚本发出的消息(但是,只能在同一台PC上对其进行测试。)

Now I am trying to implement the "listening behavior" for the native service. 现在,我正在尝试为本机服务实现“监听行为”。 The application seems to work fine, without crashing. 该应用程序似乎可以正常运行,而不会崩溃。 Yet it doesn't receive anything, although following code seems fine: 尽管下面的代码看起来不错,但是它什么也没收到:

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;
    }
}

The application is running fine in the emulator, except for the fact, that the service stalls when calling "UDPSocket::listen()" - I guess it's due the fact that I am in blocking mode. 该应用程序在仿真器中运行良好,除了以下事实外,该服务在调用“ UDPSocket :: listen()”时停止运行-我想这是由于我处于阻塞模式。 It stalls and never receives anything, regardless how often I punch the send button, that floods my local network with UDP messages. 无论我按发送按钮的频率如何,它都会停顿并且永远不会收到任何东西,这会使UDP消息淹没我的本地网络。

TL;DR Are there any special configuration steps required for receiving UDP messages on the Tizen Emulator? TL; DR在Tizen仿真器上接收UDP消息是否需要任何特殊的配置步骤?

Bonus Question: I want a method to continuously watch out for incoming UDP messages. 额外的问题:我想要一种方法来不断注意传入的UDP消息。 Should I start an extra thread for the "receiver" in the service? 我是否应该为服务中的“接收器”启动额外的线程?

Ok, I fixed the problem(s). 好的,我已解决了问题。 The first mistake was an autocompletion mistake: 第一个错误是自动完成错误:

hints.ai_socktype = SOCK_DGRAM;

instead of 代替

hints.ai_family = SOCK_DGRAM;

The second mistake or better thing I forgot: Establish port forwarding. 我忘记的第二个错误或更好的事情:建立端口转发。

For future readers: When establishing port forwarding (right click on the emulator > Settings > Network), the port must be free. 对于将来的读者:在建立端口转发时(右键单击仿真器>设置>网络),该端口必须是空闲的。 If another application has already an socket bound to this port, you'll receive an error message. 如果另一个应用程序已经将套接字绑定到该端口,则会收到错误消息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM