ShadowKatStudios / OC-Minitel

Easy-to-implement networking protocol for OpenComputers
https://oc.shadowkat.net/minitel/
Mozilla Public License 2.0
41 stars 12 forks source link

What is the proper way to use streams? #33

Closed misterzirillo closed 3 years ago

misterzirillo commented 3 years ago

Hello!

After playing with your library a bit (which is tremendous, BTW) I've been wondering why I would create a stream object rather than using minitel.send and event.pull. I like that I can keep a reference to the stream object to write to, but AFAIK it is functionally no different than minitel.send. Additionally, using stream:read doesn't seem to work how I expect it to. My intuition is that the stream contains data that hasn't been consumed yet and that stream:read("END") would eventually yield a value after "END" has been written, but instead it returns what is in the buffer now (I've only ever gotten nil from it, actually, so maybe I'm doing it wrong).

Anyway, I was hoping the author could provide an example of how the stream object is supposed to be used on both ends.

Thanks! I'm really enjoying this package.

LihrhaWolfe commented 3 years ago

I'm currently having the same issue, no matter what I have tried stream:read() always returns nil. It's driving me nuts trying to figure out if I screwed up or if it just doesn't work right now.

hopefully there is an answer soon.

misterzirillo commented 3 years ago

I think my initial notion of a "stream" was based on what I might get from a high level programming language. After working with this for a while I've decided that using the event API is the best way to accomplish what I am trying to do. A "stream" in this case is not a stream of events. It is useful for receiving a fixed or large, contiguous amount of information (like a file).

Working with other openOS buffers is the same way. A loop can be used to read the buffer, but if it is a tight loop that is long-running without any yielding calls then the program will block the whole lua process.

XeonSquared commented 3 years ago

Hi hello, apologies for the late response, GitHub didn't bother to notify me about this thread, among other things.

Threads are a useful abstraction and way to negotiate a connection so that you know both ends are on the same page. The whole stack was designed with sockets like this in mind, hence why :send is little more than just minitel.send using socket parameters - minitel.send is there to simplify sockets and similar usecases that want an ordered chunk of data sent to a given destination.

As for :read, it's non-blocking, because in OpenComputers, it's a hell of a lot easier to poll a bunch of sockets rather than multiplex a bunch of blocking operations - while it can be done, it's a lot more work than making socket reading blocking if you want it to be. If you don't care about more than one socket, you can even pull net_msg events and that will only wake your stuff up when you have data to read.

For examples, the FRequest stuff is fairly simple and the server can handle multiple connections at the same time because it's (ab)using the non-blocking nature of sockets.