LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Socket programming problems (https://www.linuxquestions.org/questions/programming-9/socket-programming-problems-369631/)

marri 10-04-2005 06:38 AM

Socket programming problems
 
hi

I'm trying to debug a small C++ routine that connects to a listening socket (on another machine) and sends/receives messages.

This should be a simple task but I've come across incredible problems which I can't sort out.

The routine is like this:

a) I connect to the listening socket using connec()
b) Send message on that socket
c) Use select() to wait for response from the peer
d) Send message again on the same socket (ignoring the select() return)
e) loop like this until I say stop!!!!

The problem lies in part d). It never sends the data for the second time and onwards eventhough the send() function doesn't return any error. It seems so that I can only send data once on a connecting socket.

Is that correct or am I not doing this right??

Here is the while loop doing the send(),select() and recv()

Code:

while (1)
  {
  //sleep(2);
  cout << "Sending data to peer - data: " << sSendBuffer << endl;
  cout << "bytes sent: " << send(iSocket, sSendBuffer, sizeof(cBuffer), 0) <<  endl;
 
  cout << "Waiting for response!!" << endl;
  FD_ZERO(&sSockets);               
  FD_SET(iSocket, &sSockets);
               
  sTimeout.tv_sec = 5;
  sTimeout.tv_usec = 0;

  // Select()
  iNumSocket = select(iSocket + 1, &sSockets, NULL, NULL, &sTimeout);
  if (iNumSocket < 0)
  {                               
        cout << "Select failed!" << endl;
  }
  else if (iNumSocket == 0)
  {
        cout << "Timed out " << endl;
  }               
  else if (FD_ISSET(iSocket, &sSockets))
  {                               
        // Read from the socket       
        memset (cBuffer, 0, sizeof(cBuffer));
        int iNumRead = recv(iSocket, cBuffer, 48, 0);
               
        // If recv() returned 0 bytes it means that the remote host
        // has closed the socket!
        if (iNumRead <= 0)
        {
                cout << "Read failed" << endl;
        }
        cout << "Server responded: " << cBuffer << endl;                               
  }
  ++iCount;       
  sprintf(sSendBuffer,"GETMSG:%d", iCount);
}

here is the connect function

Code:


  struct hostent *pHost;
  struct sockaddr_in sAddr;
  int iOpt = 1;
  fd_set sSocket, sError;
  struct timeval sTimeout;
  int iReadSocket;

  if ((pHost = gethostbyname(cAddress)) == NULL)
  {
          return false;
  }

  if ((iSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  {
      return false;
  }

  setsockopt(iSocket, SOL_SOCKET, SO_REUSEADDR, &iOpt, sizeof(iOpt));
  memset((char *) &sAddr, 0, sizeof(sAddr));
  sAddr.sin_family = AF_INET;
  sAddr.sin_port = htons(iPort);
  sAddr.sin_addr = *((struct in_addr *) pHost->h_addr);

  if (connect(iSocket, (struct sockaddr *) &sAddr, sizeof(struct sockaddr)) ==  -1)
  {
        return false;
  }       
  return true;

Hope you can assist me.

regards
Marri

YetAnotherDave 10-04-2005 05:05 PM

Hi,

This may not be causing any problems but I noticed that you are using sizeof(cBuffer) as the third argument to send. It looks to me that it should be sizeof(sSendBuffer).


cout << "bytes sent: " << send(iSocket, sSendBuffer, sizeof(cBuffer), 0) << endl;

marri 10-04-2005 05:13 PM

thanks for the reply.

But the cBuffer is defined as follows:

char cBuffer[512];

and then the sSendBuffer is defined as follows:

char* sSendBuffer = cBuffer;

this definition does the same as malloc().

One other thing, Could it be that the recv() call, made by the server, is closing the socket after receiving ????
Is that standard configuration and if so, how can it be changed.

regards
Einar

YetAnotherDave 10-04-2005 05:30 PM

The following program is your code combined into a single function: test() . I ran it on my local machine and ran "netcat -l -p 20000" to act as a server. This seemed to work fine.

You might want to try this as well on your machine. If it works, then the problem probably is that your remote server is not behaving as you expect.

To answer your question, resetting the socket after a recv is not default behavior but the server could do it anyway for some reason. Tcpdump ad/or ethereal might give you some useful diagnostics.

- Dave

Code:

#include <stdio.h>
#include <memory.h>
#include <iostream>
#include <resolv.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

using namespace std;

char cBuffer[512];
char* sSendBuffer = cBuffer;

bool test()
{

    char *cAddress = "localhost";
    struct hostent *pHost;
    struct sockaddr_in sAddr;
    int iOpt = 1;
    fd_set sSocket, sError;
    struct timeval sTimeout;
    int iReadSocket;

    if ((pHost = gethostbyname(cAddress)) == NULL)
    {
        return false;
    }

    int iSocket;

    if ((iSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        return false;
    }

    setsockopt(iSocket, SOL_SOCKET, SO_REUSEADDR, &iOpt, sizeof(iOpt));
    memset((char *) &sAddr, 0, sizeof(sAddr));
    sAddr.sin_family = AF_INET;

    uint16_t iPort = 20000;

    sAddr.sin_port = htons(iPort);
    sAddr.sin_addr = *((struct in_addr *) pHost->h_addr);

    if (connect(iSocket, (struct sockaddr *) &sAddr, sizeof(struct sockaddr)) ==  -1)
    {
        return false;
    }

    unsigned int iCount = 0;
    while (1)
    {
        //sleep(2);
        cout << "Sending data to peer - data: " << sSendBuffer << endl;
        cout << "bytes sent: " << send(iSocket, sSendBuffer, sizeof(cBuffer), 0) <<  endl;

        fd_set sSockets;
        struct timeval sTimeout;
        int iNumSocket;


        cout << "Waiting for response!!" << endl;
        FD_ZERO(&sSockets);
        FD_SET(iSocket, &sSockets);

        sTimeout.tv_sec = 5;
        sTimeout.tv_usec = 0;

        // Select()
        iNumSocket = select(iSocket + 1, &sSockets, NULL, NULL, &sTimeout);
        if (iNumSocket < 0)
        {
            cout << "Select failed!" << endl;
        }
        else if (iNumSocket == 0)
        {
            cout << "Timed out " << endl;
        }
        else if (FD_ISSET(iSocket, &sSockets))
        {
            // Read from the socket
            memset (cBuffer, 0, sizeof(cBuffer));
            int iNumRead = recv(iSocket, cBuffer, 48, 0);

            // If recv() returned 0 bytes it means that the remote host
            // has closed the socket!
            if (iNumRead <= 0)
            {
                cout << "Read failed" << endl;
            }
            cout << "Server responded: " << cBuffer << endl;
        }
        ++iCount;
        sprintf(sSendBuffer,"GETMSG:%d", iCount);
    }
}

main()
{
    test();
}


marri 10-06-2005 03:59 AM

hi
this is a tcp buffer problem and I have tried pretty much everything to work around it so I wan to ask how is it best to ensure instant delivery using tcp sockets. I know that many people have had this problem and I've followed those instructions I have read but without any result.

I check the result from recv() and send() to insure that everything has been received and sent. But the send() function always halts after the second time,,,,,

Hope somebody has had similar problems and SOLVED it.

Marri

paulsm4 10-06-2005 04:11 PM

setsockopt (TCP_NODELAY)?


All times are GMT -5. The time now is 05:45 PM.