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
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. TCP receive 2

TCP receive 2

Scheduled Pinned Locked Moved C / C++ / MFC
sysadmin
8 Posts 3 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.
  • A Offline
    A Offline
    Archyami
    wrote on last edited by
    #1

    this is an continuous message... Below is the client code to receive 2 replies from a server: /*********/ BOOL streamclient(char* ip, unsigned short port, char* message, AString* astr_reply) { // // Create a TCP/IP stream socket // SOCKET theSocket; theSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(theSocket==INVALID_SOCKET) { eprintf("ServerHandler:streamclient()\nsocket() %s %u", ip, port); return FALSE; } // // Fill in the address structure // SOCKADDR_IN saServer; DWORD dwIPAddr=inet_addr(ip); saServer.sin_family=AF_INET; saServer.sin_addr.s_addr=*((u_long FAR*)((char*)&dwIPAddr)); saServer.sin_port=htons(port); // // connect to the server // int nRet; nRet=connect(theSocket, // Socket (LPSOCKADDR)&saServer, // Server address sizeof(struct sockaddr));// Length of server address structure if(nRet==SOCKET_ERROR) { closesocket(theSocket); eprintf("ServerHandler:streamclient()\nconnect() %s %u", ip, port); return FALSE; } // // Send data to the server // nRet=send(theSocket, // Connected socket message, // Data buffer (int)strlen(message), // Length of data 0); // Flags if(nRet==SOCKET_ERROR) { closesocket(theSocket); eprintf("ServerHandler:streamclient()\nsend() %s %u", ip, port); return FALSE; } aprintf("sent to CATOS (%s %u):\n%s", ip, port, message); // // Wait for a reply // char* szBuf; AString astr; /* receive ACK */ szBuf=(char*)malloc(sizeof(char)*(CATOS_BUFFER_SIZE+1)); if(szBuf==NULL) { eprintf("ServerHandler:streamclient()\nszBuf==NULL"); return FALSE; } nRet=recv(theSocket, // Connected socket szBuf, // Receive buffer CATOS_BUFFER_SIZE,//sizeof(szBuf), // Size of receive buffer 0); // Flags if(nRet==SOCKET_ERROR) { closesocket(theSocket); free(szBuf); eprintf("ServerHandler:streamclient()\nrecv() %s %u", ip, port); return FALSE; } if(astr.Set(szBuf)) aprintf("received from server:\n%s", astr.SubString(0, ETX, TRUE)); else aprintf("received from server:\n[ACK]"); /* receive useful reply */ // clear szBuf and wait for a while so that recv() becomes ready: for(int i=0; i

    M M 2 Replies Last reply
    0
    • A Archyami

      this is an continuous message... Below is the client code to receive 2 replies from a server: /*********/ BOOL streamclient(char* ip, unsigned short port, char* message, AString* astr_reply) { // // Create a TCP/IP stream socket // SOCKET theSocket; theSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(theSocket==INVALID_SOCKET) { eprintf("ServerHandler:streamclient()\nsocket() %s %u", ip, port); return FALSE; } // // Fill in the address structure // SOCKADDR_IN saServer; DWORD dwIPAddr=inet_addr(ip); saServer.sin_family=AF_INET; saServer.sin_addr.s_addr=*((u_long FAR*)((char*)&dwIPAddr)); saServer.sin_port=htons(port); // // connect to the server // int nRet; nRet=connect(theSocket, // Socket (LPSOCKADDR)&saServer, // Server address sizeof(struct sockaddr));// Length of server address structure if(nRet==SOCKET_ERROR) { closesocket(theSocket); eprintf("ServerHandler:streamclient()\nconnect() %s %u", ip, port); return FALSE; } // // Send data to the server // nRet=send(theSocket, // Connected socket message, // Data buffer (int)strlen(message), // Length of data 0); // Flags if(nRet==SOCKET_ERROR) { closesocket(theSocket); eprintf("ServerHandler:streamclient()\nsend() %s %u", ip, port); return FALSE; } aprintf("sent to CATOS (%s %u):\n%s", ip, port, message); // // Wait for a reply // char* szBuf; AString astr; /* receive ACK */ szBuf=(char*)malloc(sizeof(char)*(CATOS_BUFFER_SIZE+1)); if(szBuf==NULL) { eprintf("ServerHandler:streamclient()\nszBuf==NULL"); return FALSE; } nRet=recv(theSocket, // Connected socket szBuf, // Receive buffer CATOS_BUFFER_SIZE,//sizeof(szBuf), // Size of receive buffer 0); // Flags if(nRet==SOCKET_ERROR) { closesocket(theSocket); free(szBuf); eprintf("ServerHandler:streamclient()\nrecv() %s %u", ip, port); return FALSE; } if(astr.Set(szBuf)) aprintf("received from server:\n%s", astr.SubString(0, ETX, TRUE)); else aprintf("received from server:\n[ACK]"); /* receive useful reply */ // clear szBuf and wait for a while so that recv() becomes ready: for(int i=0; i

      M Offline
      M Offline
      mpk1979
      wrote on last edited by
      #2

      hi, is it showing exception which executing aprintf statement or after returning from aprintf statement mpk1979

      A 1 Reply Last reply
      0
      • M mpk1979

        hi, is it showing exception which executing aprintf statement or after returning from aprintf statement mpk1979

        A Offline
        A Offline
        Archyami
        wrote on last edited by
        #3

        If a printf("aprintf OK"); is added after calling aprintf, the message "aprintf OK" can be shown. then goes to return TRUE; But printf("returned") if added in the lower function, it does not show "returned". So, I think something causes the exception for exiting the upper function. Please advise.

        1 Reply Last reply
        0
        • A Archyami

          this is an continuous message... Below is the client code to receive 2 replies from a server: /*********/ BOOL streamclient(char* ip, unsigned short port, char* message, AString* astr_reply) { // // Create a TCP/IP stream socket // SOCKET theSocket; theSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(theSocket==INVALID_SOCKET) { eprintf("ServerHandler:streamclient()\nsocket() %s %u", ip, port); return FALSE; } // // Fill in the address structure // SOCKADDR_IN saServer; DWORD dwIPAddr=inet_addr(ip); saServer.sin_family=AF_INET; saServer.sin_addr.s_addr=*((u_long FAR*)((char*)&dwIPAddr)); saServer.sin_port=htons(port); // // connect to the server // int nRet; nRet=connect(theSocket, // Socket (LPSOCKADDR)&saServer, // Server address sizeof(struct sockaddr));// Length of server address structure if(nRet==SOCKET_ERROR) { closesocket(theSocket); eprintf("ServerHandler:streamclient()\nconnect() %s %u", ip, port); return FALSE; } // // Send data to the server // nRet=send(theSocket, // Connected socket message, // Data buffer (int)strlen(message), // Length of data 0); // Flags if(nRet==SOCKET_ERROR) { closesocket(theSocket); eprintf("ServerHandler:streamclient()\nsend() %s %u", ip, port); return FALSE; } aprintf("sent to CATOS (%s %u):\n%s", ip, port, message); // // Wait for a reply // char* szBuf; AString astr; /* receive ACK */ szBuf=(char*)malloc(sizeof(char)*(CATOS_BUFFER_SIZE+1)); if(szBuf==NULL) { eprintf("ServerHandler:streamclient()\nszBuf==NULL"); return FALSE; } nRet=recv(theSocket, // Connected socket szBuf, // Receive buffer CATOS_BUFFER_SIZE,//sizeof(szBuf), // Size of receive buffer 0); // Flags if(nRet==SOCKET_ERROR) { closesocket(theSocket); free(szBuf); eprintf("ServerHandler:streamclient()\nrecv() %s %u", ip, port); return FALSE; } if(astr.Set(szBuf)) aprintf("received from server:\n%s", astr.SubString(0, ETX, TRUE)); else aprintf("received from server:\n[ACK]"); /* receive useful reply */ // clear szBuf and wait for a while so that recv() becomes ready: for(int i=0; i

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

          I'm not sure what the server is sending you, but you send this many bytes

          (int)strlen(message), // Length of data

          to the server (you're not sending the NULL terminator at the end of the message). On the first receive from the server you assume the string is NULL terminated

          if(astr.Set(szBuf))

          Try either sending "strlen(message) + 1" bytes or using "if(astr.Set(szBuf,nRet))" instead of "if(astr.Set(szBuf))". Mark

          A 1 Reply Last reply
          0
          • M Mark Salsbery

            I'm not sure what the server is sending you, but you send this many bytes

            (int)strlen(message), // Length of data

            to the server (you're not sending the NULL terminator at the end of the message). On the first receive from the server you assume the string is NULL terminated

            if(astr.Set(szBuf))

            Try either sending "strlen(message) + 1" bytes or using "if(astr.Set(szBuf,nRet))" instead of "if(astr.Set(szBuf))". Mark

            A Offline
            A Offline
            Archyami
            wrote on last edited by
            #5

            Thanks Mark! I tried to send "strlen(message) + 1" bytes to the server. The exception appears less often, but still occurs. The exception message is: "DAMAGE: after Normal block (#1409) at 0x0032EF20" I cannot use 'try' to catch it. Using debug mode fails to locate the error line... Please help me again. It should be very close to the solution. Thanks!

            M 1 Reply Last reply
            0
            • A Archyami

              Thanks Mark! I tried to send "strlen(message) + 1" bytes to the server. The exception appears less often, but still occurs. The exception message is: "DAMAGE: after Normal block (#1409) at 0x0032EF20" I cannot use 'try' to catch it. Using debug mode fails to locate the error line... Please help me again. It should be very close to the solution. Thanks!

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

              Archyami wrote:

              I tried to send "strlen(message) + 1" bytes to the server. The exception appears less often, but still occurs

              That's fine. You need to do the same on your sends FROM the server as well otherwise this line is going to be problematic on the client side: if(astr.Set(szBuf)) You are still assuming that szBuf has a NULL terminator. Whether or not this is causing the exception I don't know. A few notes and questions... You allocate a receive buffer CATOS_BUFFER_SIZE+1 bytes in length but only recv CATOS_BUFFER_SIZE bytes into it. Why? I believe you mentioned using blocking sockets in another post. If so, the Sleep() call is useless since the second recv call will block until you receive some more bytes or the socket closes or error occurs. It looks like you're waiting until "for sure" all the bytes have arrived before trying the second receive. This may work for a few "packets" but is very inefficient for a tcp socket. Instead, it works better to keep calling recv until you get the bytes you are expecting (remember, recv() won't always give them all to you in one call). To receive CATOS_BUFFER_SIZE bytes try something like:

              szBuf=(char*)malloc(sizeof(char)*(CATOS_BUFFER_SIZE+1));

              int TotalBytesReceived = 0;

              while (TotalBytesReceived < CATOS_BUFFER_SIZE)
              {
              int CurBytesReceived = ::recv(theSocket, &szBuf[TotalBytesReceived], CATOS_BUFFER_SIZE - TotalBytesReceived, 0);
              if (CurBytesReceived == 0)
              {
              // connection gracefully closed!!
              break;
              }
              else if (CurBytesReceived == SOCKET_ERROR)
              {
              int rc = WSAGetLastError();
              if (rc != WSAEWOULDBLOCK)
              {
              break; // socket error occurred!!
              }
              }
              else
              {
              TotalBytesReceived += CurBytesReceived;
              }
              }

              if (TotalBytesReceived == CATOS_BUFFER_SIZE)
              {
              // Successfully received CATOS_BUFFER_SIZE bytes
              //do something with szBuf
              }
              else
              {
              // something happened before we received CATOS_BUFFER_SIZE bytes
              }

              Make sure you send EXACTLY CATOS_BUFFER_SIZE from the server...if you don't you'll be stuck in the loop waiting :) If you can't always send the right amount you could timeout or something. Mark EDIT: By the way, you shouldn't ever get a WSAEWOULDBLOCK error on a blocking socket. I added the check for WSAEWOULDBLOCK as an example of using a non-blocking socket. More EDITS: Bad grammer, spelling, attitude, etc. -- modified at 22:32 Thursday 19th October, 2006

              A 1 Reply Last reply
              0
              • M Mark Salsbery

                Archyami wrote:

                I tried to send "strlen(message) + 1" bytes to the server. The exception appears less often, but still occurs

                That's fine. You need to do the same on your sends FROM the server as well otherwise this line is going to be problematic on the client side: if(astr.Set(szBuf)) You are still assuming that szBuf has a NULL terminator. Whether or not this is causing the exception I don't know. A few notes and questions... You allocate a receive buffer CATOS_BUFFER_SIZE+1 bytes in length but only recv CATOS_BUFFER_SIZE bytes into it. Why? I believe you mentioned using blocking sockets in another post. If so, the Sleep() call is useless since the second recv call will block until you receive some more bytes or the socket closes or error occurs. It looks like you're waiting until "for sure" all the bytes have arrived before trying the second receive. This may work for a few "packets" but is very inefficient for a tcp socket. Instead, it works better to keep calling recv until you get the bytes you are expecting (remember, recv() won't always give them all to you in one call). To receive CATOS_BUFFER_SIZE bytes try something like:

                szBuf=(char*)malloc(sizeof(char)*(CATOS_BUFFER_SIZE+1));

                int TotalBytesReceived = 0;

                while (TotalBytesReceived < CATOS_BUFFER_SIZE)
                {
                int CurBytesReceived = ::recv(theSocket, &szBuf[TotalBytesReceived], CATOS_BUFFER_SIZE - TotalBytesReceived, 0);
                if (CurBytesReceived == 0)
                {
                // connection gracefully closed!!
                break;
                }
                else if (CurBytesReceived == SOCKET_ERROR)
                {
                int rc = WSAGetLastError();
                if (rc != WSAEWOULDBLOCK)
                {
                break; // socket error occurred!!
                }
                }
                else
                {
                TotalBytesReceived += CurBytesReceived;
                }
                }

                if (TotalBytesReceived == CATOS_BUFFER_SIZE)
                {
                // Successfully received CATOS_BUFFER_SIZE bytes
                //do something with szBuf
                }
                else
                {
                // something happened before we received CATOS_BUFFER_SIZE bytes
                }

                Make sure you send EXACTLY CATOS_BUFFER_SIZE from the server...if you don't you'll be stuck in the loop waiting :) If you can't always send the right amount you could timeout or something. Mark EDIT: By the way, you shouldn't ever get a WSAEWOULDBLOCK error on a blocking socket. I added the check for WSAEWOULDBLOCK as an example of using a non-blocking socket. More EDITS: Bad grammer, spelling, attitude, etc. -- modified at 22:32 Thursday 19th October, 2006

                A Offline
                A Offline
                Archyami
                wrote on last edited by
                #7

                I modified the server "send" with data length +1. The exception does not occur. Thanks very much, Mark! I have a few questions: 1. The message eg. equals "abc". Its length is 3. Why should I send its length as 4? (The server is checked to send data within the length of CATOS_BUFFER_SIZE.) 2. The recv buffer is allocated with 1 more byte for safe (may be it is a risk...) My design is that if CATOS_BUFFER_SIZE==10 and message comes from the server as "1234567890", it can hold the message. Indeed, a terminator is at the end (here is '0'). If '\0' is padded by the server, it can still hold the message. '\0' is padded automatically for initializing an char array. Please advise if my analysis is wrong. 3. If the server is checked to send data within the length of CATOS_BUFFER_SIZE, is it possible that the client recv() may receive the message sereral times instead of once? I mean: recv() holds the application (thread). 'several times' refers to 1 recv() receives a part of the message, several recv() receives all message 'packages'. Please advise. :)

                M 1 Reply Last reply
                0
                • A Archyami

                  I modified the server "send" with data length +1. The exception does not occur. Thanks very much, Mark! I have a few questions: 1. The message eg. equals "abc". Its length is 3. Why should I send its length as 4? (The server is checked to send data within the length of CATOS_BUFFER_SIZE.) 2. The recv buffer is allocated with 1 more byte for safe (may be it is a risk...) My design is that if CATOS_BUFFER_SIZE==10 and message comes from the server as "1234567890", it can hold the message. Indeed, a terminator is at the end (here is '0'). If '\0' is padded by the server, it can still hold the message. '\0' is padded automatically for initializing an char array. Please advise if my analysis is wrong. 3. If the server is checked to send data within the length of CATOS_BUFFER_SIZE, is it possible that the client recv() may receive the message sereral times instead of once? I mean: recv() holds the application (thread). 'several times' refers to 1 recv() receives a part of the message, several recv() receives all message 'packages'. Please advise. :)

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

                  Archyami wrote:

                  1. The message eg. equals "abc". Its length is 3. Why should I send its length as 4? (The server is checked to send data within the length of CATOS_BUFFER_SIZE.)

                  I don't think you SHOULD send 4. I was just trying to fix your exception before. If you have 3 bytes to send then send 3 bytes :)

                  Archyami wrote:

                  2. The recv buffer is allocated with 1 more byte for safe (may be it is a risk...) My design is that if CATOS_BUFFER_SIZE==10 and message comes from the server as "1234567890", it can hold the message. Indeed, a terminator is at the end (here is '0'). If '\0' is padded by the server, it can still hold the message. '\0' is padded automatically for initializing an char array. Please advise if my analysis is wrong.

                  If you want to send the '\0' WITH the string of characters "1234567890" then you need to send 11 bytes. It is up to YOU to send and receive the correct amount of bytes.

                  Archyami wrote:

                  3. If the server is checked to send data within the length of CATOS_BUFFER_SIZE, is it possible that the client recv() may receive the message sereral times instead of once? I mean: recv() holds the application (thread). 'several times' refers to 1 recv() receives a part of the message, several recv() receives all message 'packages'.

                  I'll try to explain this again...TCP knows NOTHING about "packages" or "packets" - it only knows a STREAM of bytes. You can send 1000 bytes and on the other end you may receive all 1000 bytes in one call to recv(), you may receive 10 bytes in one call to recv() and 990 bytes in the next call to recv(), etc.. It's all about BYTES and it's up to you keep calling recv() until you get the number of bytes you are expecting. If you always want to recv the same number of bytes you send then you need to use a message/datagram based protocol like UDP. I suggest reading this Windows Sockets 2[^]. Mark

                  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