Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Bug Potential bug (difference between WebSocket and UDP)

Discussion in 'Unity Transport' started by MariuszKowalczyk, Mar 24, 2023.

  1. MariuszKowalczyk

    MariuszKowalczyk

    Joined:
    Nov 29, 2011
    Posts:
    301
    UDP:
    - When I disconnect the client, the server doesn't know about it and is waiting for the timeout.
    - When I close the server, the client doesn't know about it and is waiting for the timeout.
    I don't know if this is the behavior that is expected. If yes then I will have to send an RPC before disconnecting to inform the other side.

    WebSocket:
    - When I disconnect the client, the server knows about it immediately.
    - When I close the server, the client knows about it immediately too.

    So the behavior is different. I am not sure if it is a bug or an expected behavior.
     
  2. simon-lemay-unity

    simon-lemay-unity

    Unity Technologies

    Joined:
    Jul 19, 2021
    Posts:
    427
    You need to ensure at least one update occurs after disconnecting to ensure the disconnection notification gets sent to the remote peer. For example:
    Code (CSharp):
    1. driver.Disconnect(connection);
    2. driver.ScheduleUpdate().Complete(); // <--
    3. driver.Dispose();
    Without an update after the disconnection, the transport can't send any message to let the remote peer know that the connection is being closed. That's not really an issue with WebSockets because disposing of the driver will close the TCP connection (haven't checked in Wireshark, but I'm guessing it's sending a RST to the remote).

    I agree that this is not obvious behavior though. I'll update our documentation to clarify this.
     
  3. MariuszKowalczyk

    MariuszKowalczyk

    Joined:
    Nov 29, 2011
    Posts:
    301
    @simon-lemay-unity
    Thank you for the answer. It almost work, but I think that I found a potential bug.

    When I use ScheduleUpdate() it seems to work as you described.
    But when I use ScheduleFleshSend() instead, it only works when I close the client connection on the server, when I close the connection on the client, the server is not informed about it.
     
  4. simon-lemay-unity

    simon-lemay-unity

    Unity Technologies

    Joined:
    Jul 19, 2021
    Posts:
    427
    That's expected. It's really an update job that needs to run for the notification to be sent. Some extra processing is required to properly close a connection and that processing only happens in update jobs, not send jobs.
     
    MariuszKowalczyk likes this.
  5. MariuszKowalczyk

    MariuszKowalczyk

    Joined:
    Nov 29, 2011
    Posts:
    301
    Thank you for the clarification.

    As we are talking about the events, I would like to use it to ask questions that are not related directly to this thread:
    When I pop the events from the queue are they ordered in any way? I mean:
    - Is the first pipeline on the list (the one I added first) going to be popped first? That would allow me to pop RPC before state updates
    - Are the Connect/Disconnect events going to be popped before Data events? (I think the answer to this one is NO).
     
  6. simon-lemay-unity

    simon-lemay-unity

    Unity Technologies

    Joined:
    Jul 19, 2021
    Posts:
    427
    Connect events are generated first, then data events, then disconnect events. So it's possible to pop a connect event, and then pop a data event. Or pop a data event and then pop a disconnect event. But it's not possible to pop a disconnect event and then pop a data event for the same connection. (There is an exception to this rule where data events may be generated before connect events if they originate from a pipeline. The only example I can think of is if a packet was delayed by the simulator pipeline. Its data event will be generated before connect events of other connections.)

    Data events are generated according to the order in which the associated packets were received from the network. Pipelines do not affect the order in which they are delivered. So for example if you receive packets A then B, you'll get data events for A and then B, even if B is from an "earlier" pipeline in the list.
     
    MariuszKowalczyk likes this.
  7. MariuszKowalczyk

    MariuszKowalczyk

    Joined:
    Nov 29, 2011
    Posts:
    301
    I am testing what I posted in this topic. I call the driver.ScheduleUpdate().Complete(); as suggested and on UDP all seems to work.

    1)
    But on WebSocket it looks like 50% or more of the time when I disconnect the client on the client side, the server is not being informed about it but is waiting for the disconnect timeout.

    Also I noticed that if it is working then it is working many times in a row (or maybe even all the time), but when it is not working, then it seems to never work till I restart the application (or maybe just the server). I am not 100% sure if this is true all the time.

    2)
    The second problem I have is in this situation:
    - The client is being disconnected (like described above or just due to the Internet not working on the client side) and the server is waiting for the disconnection timeout.
    - Now before this timeout the same client connects again.
    - When the disconnect timeout finally takes place, I see an exception (it occurs ONLY on WebSocket, I tested on UDP and there is no problem):
    I am not sure if this exception is on the Client or on the Server side as at the moment I test them using the same application. It is probably on the server side.
     
    Last edited: Apr 8, 2023
  8. simon-lemay-unity

    simon-lemay-unity

    Unity Technologies

    Joined:
    Jul 19, 2021
    Posts:
    427
    Regarding the first problem, could you try capturing the traffic (with a tool like Wireshark) when the disconnection does not correctly occur? I'm wondering if perhaps the TCP disconnection handshake does not have enough time to complete and the sockets are now stuck in time wait. But I'd expect that to occur only if the client process is still alive after the disconnection. Can you reproduce this with the client as a separate application? Upon process termination, the OS would kill the connection with a RST and that will cause an immediate disconnection notification.

    Thanks for reporting that second problem. I'll try to have a look soon. In the meantime, if you are able to reproduce this with Burst disabled (you can disable it under the Jobs menu), that would provide a clearer stack trace which would be helpful to debug this.
     
  9. MariuszKowalczyk

    MariuszKowalczyk

    Joined:
    Nov 29, 2011
    Posts:
    301
    @simon-lemay-unity

    Here is the error from the second problem with the burst disabled:
    I also spent a few minutes trying to reproduce the first problem with the client built as a WebGL (as the problem is only on the WebGL). I was testing using the localhost and Chrome. So far I was not able to reproduce the problem. So maybe it only occur when client and server run from the same application or maybe I need more tries to reproduce it.

    I am on macOS 12.6.
     
    Last edited: Apr 12, 2023
  10. simon-lemay-unity

    simon-lemay-unity

    Unity Technologies

    Joined:
    Jul 19, 2021
    Posts:
    427
    Thanks for the detailed stack trace! I've filed a bug on our end so that we can properly track this issue. We'll look into it in the coming days.
     
  11. MariuszKowalczyk

    MariuszKowalczyk

    Joined:
    Nov 29, 2011
    Posts:
    301
    I would like to ask it the two problems I described in this topic were fixed.
     
  12. simon-lemay-unity

    simon-lemay-unity

    Unity Technologies

    Joined:
    Jul 19, 2021
    Posts:
    427
    Yes, both issues should have been addressed in version 2.0.2 of the package.