Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

send and receive from client? #8

Closed
avlapp opened this issue Aug 24, 2022 · 6 comments
Closed

send and receive from client? #8

avlapp opened this issue Aug 24, 2022 · 6 comments

Comments

@avlapp
Copy link

avlapp commented Aug 24, 2022

https://pkg.go.dev/github.com/loffa/gosc#Client.SendAndReceiveMessage

Other osc implementations are sending from a server, which then is able to receive a reply.

http://dsacre.github.io/pyliblo/doc/

"To enabled this a SendTo (analogue to PacketConn.WriteTo) was added to the Server struct. "
hypebeast/go-osc#51

@loffa
Copy link
Owner

loffa commented Aug 24, 2022

The standards of the server/client model is that the server listens for incoming connections, and replies to them if needed. The server have no idea that a client exist until that client connect and sends a message. There are no other OSC Server implementations that randomly can send data to a client, since this would mean the roles where reversed. If you initiate the connection, you are the client... A software can be both a server and a client (bi-directional communication).

If you want to reply to any OSC message received to the server this can be handled in the MessageHandler that you create. The first argument to the Handle function is a writer for writing responses back to the client.

The link to go-osc you provided adds the same functionality as my Client.SendAndReceiveMessage. But wrongly using the server struct.

@loffa loffa closed this as completed Aug 24, 2022
@avlapp
Copy link
Author

avlapp commented Aug 24, 2022

Thanks, makes sense I think. I didn't manage yet to get a reply (could be me), but looking at the code, there is no timeout functionality, so you get stuck when there is no reply. Given that it's udp, a reply is not guaranteed afaik.

I found a example of such timeout here:
https://github.com/scgolang/osc/blob/master/pingpong_example_test.go#L113

@loffa
Copy link
Owner

loffa commented Aug 24, 2022

Firstly UDP and TCP does not govern the application response protocol (OSC in this case). An UDP connection is not guaranteed to deliver packets, TCP uses a ack principle for ensuring that the package is delivered. But the OSC Server in use is not made to send a response on the application level either way.

The Client.SendAndReceiveMessage method is blocking without timeout as per the documentation. However, the client can still register message handlers for replies, the method just acts as a message handlers for a message on the same address from the server and waits for it. You could instead use Client.SendMesaage and create a listener first for the response. This is why I am hesitant to create a timeout since the application internally is still asynchronous.

@loffa loffa reopened this Aug 24, 2022
@loffa loffa closed this as completed Aug 24, 2022
@avlapp
Copy link
Author

avlapp commented Aug 24, 2022

I see. Got it working with c.SendMessage and a c.ReceiveMessageFunc. Then I can imagine (as a newbie) it would be handy to be able to pass a chan (done) variable to that ReceiveMessageFunc, that's a technique which I saw a lot in this package:
https://github.com/scgolang/osc/blob/master/pingpong_example_test.go

Now the question is why c.SendAndReceiveMessage didn't work I guess.

@avlapp
Copy link
Author

avlapp commented Aug 28, 2022

I was able to make a new type (pointer bool field in a struct is what I did), then add a oscMessageHandler as method of that new type and then set the bool to true if a 'pong' has received. Then main can exit.

type Ping struct {
done bool
}

func (p *Ping) oscMessageHandler(msg *gosc.Message) {
fmt.Println(msg.Address)
fmt.Println(msg.Arguments)
p.done = true
}

// main
pong := &Ping{false}

client.ReceiveMessageFunc("/pong", pong.oscMessageHandler)

Then a for (while) loop in main to check if pong.done is still false.

edit: or using a global variable.

@avlapp
Copy link
Author

avlapp commented Sep 12, 2022

All though your server client distinction makes sense in general, I still don't think this strict distinction is correct when it comes to OSC. I think a application can be both server and client (maybe the wrong wording then). This is also implemented by the much used liblo library it seems:

"Send a OSC formatted message to the address specified, from the same socket as the specified server. "

http://liblo.sourceforge.net/docs/group__liblo.html#gaa4a314562b09e2fd00749a5d0b4d0955

"The unit of transmission of OSC is an OSC Packet. Any application that sends OSC Packets is an OSC Client; any application that receives OSC Packets is an OSC Server."
https://opensoundcontrol.stanford.edu/spec-1_0.html

But in Best Practices for Open Sound Control document:

"This distinction is not necessary"

"4.6 Network Topology and Routing
The OSC 1.0 Specification included some lan-
guage regarding OSC client and server end-
points. In fact this distinction is not necessary
and OSC may be used on unidirectional trans-
ports, and more complex network topologies in-
cluding multicast, broadcast and peer-to-peer.

The OSCgroups project provides a method for
achieving multicast routing and automatic NAT
traversal on the internet [Bencina, 2009].
A shortcoming of many current OSC imple-
mentations using UDP/IP is missing support
for bidirectional messaging.
As a best practice
implementations should try to leverage as much
information as the transport layer can provide,
as this makes more simple the task of configu-
ration of the endpoint addresses in applications
as well as stateful inspection at lower layers."
https://opensoundcontrol.stanford.edu/files/osc-best-practices-final.pdf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants