Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. TCP client/server data exchange

TCP client/server data exchange

Scheduled Pinned Locked Moved C / C++ / MFC
tutorialcomsysadminhelpquestion
32 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Jorgen Sigvardsson

    JudyL_FL wrote:

    There is no guarantee that a single recv call on one end of a connection will get all the data sent with a single send call on the other end.

    It is possible with fixed sized messages, and blocking sockets. Although, I don't think the message sizes are fixed, because he mentions parsing messages, separated with a ;

    -- Kein Mitleid Für Die Mehrheit

    J Offline
    J Offline
    JudyL_MD
    wrote on last edited by
    #21

    Right you are on both accounts - one recv will do if you know the packet size and the OP is not using a fixed size packet

    1 Reply Last reply
    0
    • M Mark Salsbery

      Joergen Sigvardsson wrote:

      It is possible with fixed sized messages

      Not guaranteed.  Even with fixed sized messages, there's NO guarantee the TCP protocol won't deliver it in different size chunks.  Only a datagram protocol guarantees this. :) Mark

      Mark Salsbery Microsoft MVP - Visual C++ :java:

      J Offline
      J Offline
      JudyL_MD
      wrote on last edited by
      #22

      He is right if it is a blocking socket. If you ask for x bytes in the recv function, it will either deliver x bytes or return a timeout indication. Judy

      M 2 Replies Last reply
      0
      • J JudyL_MD

        He is right if it is a blocking socket. If you ask for x bytes in the recv function, it will either deliver x bytes or return a timeout indication. Judy

        M Offline
        M Offline
        Mark Salsbery
        wrote on last edited by
        #23

        What's a blocking socket?  ;P Thanks Judy!! Mark

        Mark Salsbery Microsoft MVP - Visual C++ :java:

        J 1 Reply Last reply
        0
        • M Mark Salsbery

          What's a blocking socket?  ;P Thanks Judy!! Mark

          Mark Salsbery Microsoft MVP - Visual C++ :java:

          J Offline
          J Offline
          JudyL_MD
          wrote on last edited by
          #24

          Some mythical beast that I've heard about and know the legends about but have never encountered in real life. :cool:

          1 Reply Last reply
          0
          • J JudyL_MD

            He is right if it is a blocking socket. If you ask for x bytes in the recv function, it will either deliver x bytes or return a timeout indication. Judy

            M Offline
            M Offline
            Mark Salsbery
            wrote on last edited by
            #25

            Well Judy, I had to test this before I respectfully disagreed with you :) I respectfully disagree... A blocking Recv() WILL return before all bytes requested are received.  Here's the test I did - note I try to recv 512 bytes but only send 256...

            //----------------------------------------------
            // Listener/ receiver thread (started in CMYTestDlg::OnOK() below)
            //----------------------------------------------
            UINT __cdecl TestThreadProc( LPVOID pParam )
            {
                SOCKET ListenSocket;
                ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
                if (ListenSocket == INVALID_SOCKET)
                {
                    return 1;
                }

            sockaddr_in service;
                service.sin_family = AF_INET;
                service.sin_addr.s_addr = inet_addr("127.0.0.1");
                service.sin_port = htons(2460);

            if (bind( ListenSocket, (SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR)
                {
                    closesocket(ListenSocket);
                    return 1;
                }

            if (listen( ListenSocket, 1 ) == SOCKET_ERROR)
                {
                    closesocket(ListenSocket);
                    return 1;
                }

            SOCKET AcceptSocket;

            AcceptSocket = accept( ListenSocket, NULL, NULL );
                if (AcceptSocket == INVALID_SOCKET)
                {
                    closesocket(ListenSocket);
                    return 1;
                }

            BYTE *pBuf = new BYTE[512];
                BYTE *pCurBuf = pBuf;
                int BytesRemaining = 512;

            while (BytesRemaining > 0)
                {
                    int CurBytesReceived = ::recv(AcceptSocket, (char*)pCurBuf, BytesRemaining, 0);

            if (CurBytesReceived == 0) //<-- put a breakpoint here - 256 bytes will be received
                    {
                        // connection was gracefully closed

            break;
                    }
                    e

            J 1 Reply Last reply
            0
            • M Mark Salsbery

              Well Judy, I had to test this before I respectfully disagreed with you :) I respectfully disagree... A blocking Recv() WILL return before all bytes requested are received.  Here's the test I did - note I try to recv 512 bytes but only send 256...

              //----------------------------------------------
              // Listener/ receiver thread (started in CMYTestDlg::OnOK() below)
              //----------------------------------------------
              UINT __cdecl TestThreadProc( LPVOID pParam )
              {
                  SOCKET ListenSocket;
                  ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
                  if (ListenSocket == INVALID_SOCKET)
                  {
                      return 1;
                  }

              sockaddr_in service;
                  service.sin_family = AF_INET;
                  service.sin_addr.s_addr = inet_addr("127.0.0.1");
                  service.sin_port = htons(2460);

              if (bind( ListenSocket, (SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR)
                  {
                      closesocket(ListenSocket);
                      return 1;
                  }

              if (listen( ListenSocket, 1 ) == SOCKET_ERROR)
                  {
                      closesocket(ListenSocket);
                      return 1;
                  }

              SOCKET AcceptSocket;

              AcceptSocket = accept( ListenSocket, NULL, NULL );
                  if (AcceptSocket == INVALID_SOCKET)
                  {
                      closesocket(ListenSocket);
                      return 1;
                  }

              BYTE *pBuf = new BYTE[512];
                  BYTE *pCurBuf = pBuf;
                  int BytesRemaining = 512;

              while (BytesRemaining > 0)
                  {
                      int CurBytesReceived = ::recv(AcceptSocket, (char*)pCurBuf, BytesRemaining, 0);

              if (CurBytesReceived == 0) //<-- put a breakpoint here - 256 bytes will be received
                      {
                          // connection was gracefully closed

              break;
                      }
                      e

              J Offline
              J Offline
              JudyL_MD
              wrote on last edited by
              #26

              Can you try calling WSAGetLastError after you receive the partial bytes? I'm curious if it is set to show the timeout. According to the documentation, recv should either read all or timeout. The docs do say: Windows Sockets 2 does not define any standard blocking time-out mechanism for this function I think we're hitting this case - the receive has timed out and who knows how the function is reporting the timeout. I think we can safely say the following: For a blocking socket, you need to check the result from the recv and if you don't get the requested number of bytes, you have hit the timeout condition and need to handle it accordingly. Judy

              M 2 Replies Last reply
              0
              • J JudyL_MD

                Can you try calling WSAGetLastError after you receive the partial bytes? I'm curious if it is set to show the timeout. According to the documentation, recv should either read all or timeout. The docs do say: Windows Sockets 2 does not define any standard blocking time-out mechanism for this function I think we're hitting this case - the receive has timed out and who knows how the function is reporting the timeout. I think we can safely say the following: For a blocking socket, you need to check the result from the recv and if you don't get the requested number of bytes, you have hit the timeout condition and need to handle it accordingly. Judy

                M Offline
                M Offline
                Mark Salsbery
                wrote on last edited by
                #27

                JudyL_FL wrote:

                Can you try calling WSAGetLastError after you receive the partial bytes?

                Sure :) WSAGetLastError() returns 0; A long time ago, while writing some of my first communication code, I got bit by this (using pipes actually, but it made me look at my sockets code) and it taught me to read the documentation thoroughly (which I wasn't doing apparently :)).  That's when I found this: "For connection-oriented sockets (type SOCK_STREAM for example), calling recv will return as much data as is currently available—up to the size of the buffer specified." FWIW, This also applies to pipes. So, any amount of bytes returned by recv() indicates success.  This can be seen especially when receiving amounts larger than the socket buffer, where the protocol MUST return a buffer full of data to make room to receive more. This seems to be the number one thing overlooked by beginner socket programmers. I studied MS's implementation of TCP a while back, and there is a timeout involved internally, but it's not an error of any kind.  I believe by default it's 200ms (that's the number that comes to mind) before a recv() returns what it has currently buffered.  That's what makes it inefficient to always request more bytes than you're expecting. Mark

                Mark Salsbery Microsoft MVP - Visual C++ :java:

                J 1 Reply Last reply
                0
                • J JudyL_MD

                  Can you try calling WSAGetLastError after you receive the partial bytes? I'm curious if it is set to show the timeout. According to the documentation, recv should either read all or timeout. The docs do say: Windows Sockets 2 does not define any standard blocking time-out mechanism for this function I think we're hitting this case - the receive has timed out and who knows how the function is reporting the timeout. I think we can safely say the following: For a blocking socket, you need to check the result from the recv and if you don't get the requested number of bytes, you have hit the timeout condition and need to handle it accordingly. Judy

                  M Offline
                  M Offline
                  Mark Salsbery
                  wrote on last edited by
                  #28

                  Mark Salsbery wrote:

                  and it taught me to read the documentation thoroughly

                  BTW, I wasn't implying that you don't read the docs - I meant that was a turning point for me, which is why I remember it vividly :) Mark

                  Mark Salsbery Microsoft MVP - Visual C++ :java:

                  J 1 Reply Last reply
                  0
                  • M Mark Salsbery

                    JudyL_FL wrote:

                    Can you try calling WSAGetLastError after you receive the partial bytes?

                    Sure :) WSAGetLastError() returns 0; A long time ago, while writing some of my first communication code, I got bit by this (using pipes actually, but it made me look at my sockets code) and it taught me to read the documentation thoroughly (which I wasn't doing apparently :)).  That's when I found this: "For connection-oriented sockets (type SOCK_STREAM for example), calling recv will return as much data as is currently available—up to the size of the buffer specified." FWIW, This also applies to pipes. So, any amount of bytes returned by recv() indicates success.  This can be seen especially when receiving amounts larger than the socket buffer, where the protocol MUST return a buffer full of data to make room to receive more. This seems to be the number one thing overlooked by beginner socket programmers. I studied MS's implementation of TCP a while back, and there is a timeout involved internally, but it's not an error of any kind.  I believe by default it's 200ms (that's the number that comes to mind) before a recv() returns what it has currently buffered.  That's what makes it inefficient to always request more bytes than you're expecting. Mark

                    Mark Salsbery Microsoft MVP - Visual C++ :java:

                    J Offline
                    J Offline
                    JudyL_MD
                    wrote on last edited by
                    #29

                    Mark Salsbery wrote:

                    WSAGetLastError() returns 0;

                    I was curious - it was easier to have you check since you had working code. How long does your recv sit before it returns? Never mind, it's not important. I vaguely remember some socket I did a looooong while back that (I think) waited a whole lot longer than your 200ms. Too far in the past to remember the details or if I had set a timeout value or it was using the built-in one. This may have been on CE, now that I think about it and that's a whole 'nother kettle of sockets. If it wasn't CE, it was long enough ago that it was at least as old as NT4. I think we have our answer - always check the number of bytes received :-D Judy

                    M 1 Reply Last reply
                    0
                    • M Mark Salsbery

                      Mark Salsbery wrote:

                      and it taught me to read the documentation thoroughly

                      BTW, I wasn't implying that you don't read the docs - I meant that was a turning point for me, which is why I remember it vividly :) Mark

                      Mark Salsbery Microsoft MVP - Visual C++ :java:

                      J Offline
                      J Offline
                      JudyL_MD
                      wrote on last edited by
                      #30

                      no offense taken (especially since I quoted the docs a reply or so back), have a .... wait, where's the beer emoticon??? aaaargh Judy

                      M 1 Reply Last reply
                      0
                      • J JudyL_MD

                        Mark Salsbery wrote:

                        WSAGetLastError() returns 0;

                        I was curious - it was easier to have you check since you had working code. How long does your recv sit before it returns? Never mind, it's not important. I vaguely remember some socket I did a looooong while back that (I think) waited a whole lot longer than your 200ms. Too far in the past to remember the details or if I had set a timeout value or it was using the built-in one. This may have been on CE, now that I think about it and that's a whole 'nother kettle of sockets. If it wasn't CE, it was long enough ago that it was at least as old as NT4. I think we have our answer - always check the number of bytes received :-D Judy

                        M Offline
                        M Offline
                        Mark Salsbery
                        wrote on last edited by
                        #31

                        JudyL_FL wrote:

                        was curious - it was easier to have you check since you had working code.

                        I knew that hehe.

                        JudyL_FL wrote:

                        How long does your recv sit before it returns?

                        About a second (accurate, huh?) from when I hit the OK button - that includes the 1000ms Sleep() in my fancy thread synchronization. I agree it doesn't matter - the internal "timeout" is implementation specific.  Different protocol stack vendors are free to implement the internals the way they want.  That's why I only have MS specific info (and even that is vague now). recv() API behavior, however, is well defined.

                        JudyL_FL wrote:

                        I think we have our answer - always check the number of bytes received

                        Agreed! :beer: Mark

                        Mark Salsbery Microsoft MVP - Visual C++ :java:

                        1 Reply Last reply
                        0
                        • J JudyL_MD

                          no offense taken (especially since I quoted the docs a reply or so back), have a .... wait, where's the beer emoticon??? aaaargh Judy

                          M Offline
                          M Offline
                          Mark Salsbery
                          wrote on last edited by
                          #32

                          :beer: :beer: :beer: :)

                          Mark Salsbery Microsoft MVP - Visual C++ :java:

                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • World
                          • Users
                          • Groups