Thread: WSASend & WSARecv :: Winsock

  1. #1
    Registered User
    Join Date
    Nov 2001
    Posts
    1,348

    WSASend & WSARecv :: Winsock

    Hi.

    I am implementing a send and receive part of a simple message program. Everything seems to work okay, except the send and receive are not in sync.

    For send, I use WSASend. I first send a "header" buffer with the same of the real data buffer. Next, I send the real data buffer.

    For receive, I use WSARecv. I first receive the "header" buffer and determine its DWORD size. I then allocate a character array of that size. Next, I receive the real data buffer based on the size.

    The problem is the "header" buffer I receive does not hold the correct data size. For example, let say the data size is 10 byte (10 characters). Instead of 10, I will get something at least in 90+ when I cast the "header" to a DWORD.

    Here is the sample code for both send and receive. Please keep me updated if you find any known problem.

    -----
    char *data = new char[4];
    data = "test";
    DWORD bufferSize = static_cast<DWORD>(strlen(data)), sentSize = 0;
    WSABUF bufferHDR,
    bufferDATA;
    char *header = new char[4];
    CString sizeCnt;
    sizeCnt.Format("%d", bufferSize);
    strcpy(header, static_cast<LPCTSTR>(sizeCnt));
    bufferHDR.len = 4;
    bufferHDR.buf = header;

    // sending first data buffer contain the size

    if (WSASend(socket, &bufferHDR, 1, &sentSize, MSG_OOB, 0, 0) == 0)
    {
    bufferDATA.len = bufferSize;
    bufferDATA.buf = data;
    sentSize = 0;
    DWORD bufferProgress = 0;

    // make sure all data gets sent
    while (sentSize < bufferSize)
    {
    if (WSASend(m_ActiveSocket, &bufferDATA, 1, &bufferProgress, MSG_OOB, 0, 0) == 0)
    {
    sentSize += bufferProgress;
    bufferProgress = 0;
    }

    else
    {
    DetermineErrorWSASend();
    sentSize = bufferSize;
    }
    }

    else
    DetermineErrorWSASend();
    -----

    -----
    DWORD bufferSize = 0,
    receivedSize = 0,
    flags = 0;
    WSABUF bufferHDR,
    bufferDATA;
    char *header = new char[4], *data;
    bufferHDR.len = 4;
    bufferHDR.buf = header;


    // reading first buffer to determine real data size
    if (WSARecv(socket, &bufferHDR, 1, &receivedSize, &flags, 0, 0) == 0)
    {
    CString x;
    bufferSize = static_cast<DWORD>(*bufferHDR.buf);
    x.Format("%s%d", "bufferSize = ", bufferSize);
    AfxMessageBox(x);

    // allocating memory based on buffer size

    data = new char[bufferSize];
    bufferDATA.len = bufferSize;
    bufferDATA.buf = data;
    receivedSize = 0;
    DWORD bufferProgress = 0;

    // make sure all buffer get read

    while (receivedSize < bufferSize)
    {
    if (WSARecv(socket, &bufferDATA, 1, &bufferProgress, &flags, 0, 0) == 0)
    {
    x.Format("%d", bufferProgress);
    AfxMessageBox(x);
    newData += *bufferDATA.buf;
    receivedSize += bufferProgress;
    }

    else
    {
    DetermineErrorWSARecv();
    receivedSize = bufferSize;
    }
    }
    delete [] data;
    delete [] header;
    }
    -----

    Thanks,
    Kuphryn

  2. #2
    Registered User johnnie2's Avatar
    Join Date
    Aug 2001
    Posts
    186
    Your WSABUF structure's buf member is apparently a void or char pointer. The receiving side assigns a string to that pointer that is composed of the size of the data buffer. So, the data that is actually put into bufferHDR.buf is the address of the string on the sender's computer. Then, the header is sent to the receiver. The receiver opens the header, thinking that the address stored in buf member is valid for its computer. However, the address that seemed valid on the sender's computer points to some random block of memory on the receiver's computer, leading to the appearance of seemingly random values after the cast. To store character data within the struct, you'd need to do something like:

    Code:
    typedef struct {
       char msgSize[10];
    } net_header;
    and strcpy() the string produced by your static cast into msgSize. That way, net_header contains real data rather than an address to data that will not be valid on both computers. Structs used for communications amongst multiple computers almost never contain pointers.
    "Optimal decisions, once made, do not need to be changed." - Robert Sedgewick, Algorithms in C

  3. #3
    Registered User
    Join Date
    Nov 2001
    Posts
    1,348
    Thanks.

    Winsock the and WSAAsyncSelect I/O Mode is more difficult than I anticipated. I will need another week or so to debug the program. There are some major flaws in my program. Most of which has to do with *timing*, i.e. when to send/receive header and when to send/receive data buffer. Remember that I am using the WSAAsyncSelect I/O Mode. It affects much mmore than I thought before I read MSDN.

    Kuphryn

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Winsock issues
    By tjpanda in forum Windows Programming
    Replies: 3
    Last Post: 12-04-2008, 08:32 AM
  2. AcceptEx with WSASend and WSARecv :: Winsock
    By kuphryn in forum Networking/Device Communication
    Replies: 2
    Last Post: 10-05-2003, 08:48 PM
  3. WSARecv and IOCP :: Winsock
    By kuphryn in forum Windows Programming
    Replies: 4
    Last Post: 12-26-2002, 09:19 PM
  4. Calling WSASend() Consecutively :: Winsock
    By kuphryn in forum Windows Programming
    Replies: 2
    Last Post: 05-17-2002, 09:30 AM
  5. WSARecv Error :: Winsock
    By kuphryn in forum Windows Programming
    Replies: 0
    Last Post: 05-15-2002, 02:25 PM