Как реализовать передачу данных по протоколу UDP с помощью brl.socket?

  1. 3 г. назад

    Помогите пожалуйста разобраться в brl.socket на простом работающем примере. Задача: передача данных между приложениями по протоколу UDP. Пример кода:
    Сервер:

    Import mojo
    Import brl
    #MOJO_AUTO_SUSPEND_ENABLED=False
    Class TestApp Extends App
            Field socketTest:Socket = New Socket
            Field dataSend:DataBuffer
            
            Method OnCreate:Int()
                    SetUpdateRate(30)
                    socketTest = New Socket("datagram")
                    socketTest.Bind("localhost", 12345)
                    socketTest.Accept()
                    dataSend = New DataBuffer(32)
                    dataSend.PokeInt(0, 1)
                    Return 0
            End
            
            Method OnUpdate:Int()
                    If KeyDown(KEY_SPACE) Then
                            socketTest.Send(dataSend, 0, 32)
                    EndIf
                    Return 0
            End
            
            Method OnRender:Int()
                    Cls(0, 0, 0)
                    SetColor(255, 255, 255)
                    DrawText("Test Server", 0, 0)
                    If KeyDown(KEY_SPACE) Then
                            DrawText("send: ", 10, 30)
                            DrawText(dataSend.PeekInt(0), 100, 30)
                            EndIf
                    Return 0
            End
            
    End Class
    
    Function Main:Int()
            New TestApp()
            Return 0
    End Function

    Клиент:

    Import mojo
    Import brl
    #MOJO_AUTO_SUSPEND_ENABLED=False
    Class TestApp Extends App
            Field socketTest:Socket = New Socket
            Field dataRecive:DataBuffer
            
            Method OnCreate:Int()
                    SetUpdateRate(30)
                    socketTest = New Socket("datagram")
                    socketTest.Bind("localhost", 12345)
                    socketTest.Accept()
                    dataRecive = New DataBuffer(32)
                    dataRecive.PokeInt(0, 0)
                    Return 0
            End
            
            Method OnUpdate:Int()
                    socketTest.Receive(dataRecive, 0, 32)
                    Return 0
            End
            
            Method OnRender:Int()
                    Cls(0, 0, 0)
                    SetColor(255, 255, 255)
                    DrawText("Test Client", 0, 0)
                    DrawText("connect", 0, 10)
                    DrawText(socketTest.RemoteAddress(), 60, 10)
                    DrawText("recive: ", 10, 40)
                    DrawText(dataRecive.PeekInt(0), 100, 40)
                    Return 0
            End
            
    End Class
    
    Function Main:Int()
            New TestApp()
            Return 0
    End Function
  2. devolonter

    6 Jun 2014 Администратор
    3 г. назад исправил devolonter

    Приветствую!

    Некоторые замечания по коду:

    Сервер
    — Accept можно использовать только для TCP сервера (протокол “server”). Для UPD мы должны отправить какие-то данные на сервер, чтобы он знал он нашем существовании.
    — Для сервера вместо Send мы должны использовать SendTo для которого нужно добавочно передавать адрес клиента

    Клиент
    — Вместо Bind и Accept нужно вызывать Connect

    Ну и еще один общий момент. Заметил, что все вызовы блокирующие, т.е. приложение будет “висеть” до тех пор пока не получит ответ. Этот так и задумано? Если все же нужно, чтобы приложение продолжало нормально работать во время ожидания ответа, используйте асинхронные вызовы. Дополнительно для данных методов будет нужно передавать “слушателя” завершения события, а также добавить вызов UpdateAsyncEvents() в OnUpdate.

    Вот исправленная версия вашего кода:

    Сервер

    Strict
    
    Import mojo
    Import brl.socket
    
    #MOJO_AUTO_SUSPEND_ENABLED=False
    
    Class TestApp Extends App
    
            Field socketTest:Socket
            Field dataSend:DataBuffer
            Field client:SocketAddress
            
            Method OnCreate:Int()
                    SetUpdateRate(30)
                    socketTest = New Socket("datagram")
                    socketTest.Bind("localhost", 12345)
                    dataSend = New DataBuffer(32)
                    
                    client = New SocketAddress()
                    socketTest.ReceiveFrom(dataSend, 0, dataSend.Length, client) 'ждем клиента
                    Return 0
            End
            
            Method OnUpdate:Int()   
                    If KeyDown(KEY_SPACE) Then
                            If (client <> Null) Then
                                    dataSend.PokeInt(0, 1)
                                    socketTest.SendTo(dataSend, 0, dataSend.Length, client)
                            End If
                    EndIf
                    Return 0
            End
            
            Method OnRender:Int()
                    Cls(0, 0, 0)
                    SetColor(255, 255, 255)
                    DrawText("Test Server", 0, 0)
                    If KeyDown(KEY_SPACE) Then
                            DrawText("send: ", 10, 30)
                            DrawText(dataSend.PeekInt(0), 100, 30)
                    EndIf
                    Return 0
            End
    
    End Class
    
    Function Main:Int()
            New TestApp()
            Return 0
    End Function

    Клиент

    Strict
    
    Import mojo
    Import brl
    
    #MOJO_AUTO_SUSPEND_ENABLED=False
    
    Class TestApp Extends App
            Field socketTest:Socket = New Socket
            Field dataRecive:DataBuffer
            
            Method OnCreate:Int()
                    SetUpdateRate(30)
                    socketTest = New Socket("datagram")
                    If ( Not socketTest.Connect("localhost", 12345)) Error "Connection failed"
                    dataRecive = New DataBuffer(32)
                    socketTest.Send(dataRecive, 0, dataRecive.Length)
                    socketTest.Receive(dataRecive, 0, dataRecive.Length)
                    Return 0
            End
            
            Method OnUpdate:Int()
                    Return 0
            End
            
            Method OnRender:Int()
                    Cls(0, 0, 0)
                    SetColor(255, 255, 255)
                    DrawText("Test Client", 0, 0)
                    DrawText("connect", 0, 10)
                    DrawText(socketTest.RemoteAddress(), 60, 10)
                    DrawText("recive: ", 10, 40)
                    DrawText(dataRecive.PeekInt(0), 100, 40)
                    Return 0
            End
    
    End Class
    
    Function Main:Int()
            New TestApp()
            Return 0
    End Function

    Также советую посмотреть примеры echoserver_udp и echoserver_tcp в папке bananas/mak

или зарегистрируйтесь чтобы комментировать!