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

Why luasocket client:send send 0 (zero) byte but return 1? #409

Open
jakitliang opened this issue Sep 23, 2023 · 6 comments
Open

Why luasocket client:send send 0 (zero) byte but return 1? #409

jakitliang opened this issue Sep 23, 2023 · 6 comments

Comments

@jakitliang
Copy link

jakitliang commented Sep 23, 2023

If client:send sends 0 byte within buffer[i, j].

But it returns the last index between [i, j]. So return value is within [1, j]

Which describe in document:

If successful, the method returns the index of the last byte within [i, j] that has been sent.

And

In case of error, the method returns nil, followed by an error message, followed by the index of the last byte within [i, j] that has been sent.

But what if client:send had send 1 one byte.

How to destinct the return value of client:send after send 1 byte and send 0 byte?

For example,

buffer = "abcd".
client:send(buffer)

But network is not good.
Or Linux socket queue is full.
Or Windows socket buffer is full.

So It doesn't send anymore buffers.

@Tieske
Copy link
Member

Tieske commented Sep 25, 2023

If this happens, then that would be a bug. In that case the question comes up; what would the proper return value be?

Possible values I can think of;

  • Should it be nil + error; if this is considered an error condition
  • return 0 to indicate it send nothing
  • return 'i-1', such that indexing operations on the input string still make sense

imho the third option would be preferred

If you can create a PR, that would be very much appreciated.

@Tieske
Copy link
Member

Tieske commented Sep 25, 2023

btw; this only applies to tcp.send, docs are here: https://lunarmodules.github.io/luasocket/tcp.html#send

@jakitliang
Copy link
Author

btw; this only applies to tcp.send, docs are here: https://lunarmodules.github.io/luasocket/tcp.html#send

If this happens, then that would be a bug. In that case the question comes up; what would the proper return value be?

Possible values I can think of;

  • Should it be nil + error; if this is considered an error condition
  • return 0 to indicate it send nothing
  • return 'i-1', such that indexing operations on the input string still make sense

imho the third option would be preferred

If you can create a PR, that would be very much appreciated.

This documentation doesn't tell about "return 0 to indicate it send nothing".

Maybe this doc should be reconsider and make improvement.

@jakitliang
Copy link
Author

btw; this only applies to tcp.send, docs are here: https://lunarmodules.github.io/luasocket/tcp.html#send

And, the tcp.recv also have problem.

While I write my own tcp proto. I found the socket never close because I doesn't triggered "io.close".

The reason I found was that tcp.recv never gave err if remote is already close sometimes.

Not every time remote close() would make tcp.recv gave err => 'close'.

After all, I found the best way is to check if tcp.recv returns 0 bytes of received data.

Those received data was the a and b part of a, err, b = tcp.recv()

To avoid remote closed is not only checking err == 'closed' but also #a == 0 and #b == 0.

But there is a problem. In some low quality(QOS) network Wifi. tcp.recv may recv slow so may recv 0 zero bytes.

If indicating remote is closed by check #a == 0 and #b == 0 is wrong is such case.

So I think this luasocket's design is almost unworkable to doing such check.

My means is that this framework is awful. How 1.7K stars it can get I don't acceptable.

@jakitliang
Copy link
Author

jakitliang commented Sep 25, 2023

And there is another bug. Sometimes a client is already tcp.accept.

After doing some network read write and close. Sometimes I see remote socket was tcp.accept again because I use socket.select({server_socket}, nil, 1) to indicate the server socket.

I've read the source code but found nothing strange.

So why this closed remote socket was being accept again? But this remote socket was a socket I created by ruby remote = TCPSocket.new().

I don't understand when remote.close() but after 2 or more seconds you can find this socket was being accept again but I didn't RENEW this socket to connect again.

This remote is already closed. why being accept again.

Why socket.select({server}) can detect a closed socket?

Oh ho~ my god!

Is the luasocket's internal cached something or some procedure doesn't finished that never closed?

@Tieske
Copy link
Member

Tieske commented Sep 26, 2023

please do not mix issues or bugs in a single github issue.

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

No branches or pull requests

2 participants