1
votes

it seems that when i use send() function (in a TCP file transfer program) like this

while((count = recv(socketConnection, buff, 100000, 0))>0)
myfile.write(buff,count);

the function recv() just waits untill the whole data comes and exits the loop when it is no more receiving any data but in a similar program for a UDP program

while((n = recvfrom(sockfd,mesg,1024,0,(struct sockaddr *)&cliaddr,&len))>0)
myfile.write(mesg,n);

the recvfrom() function just blocks and does not exit the loop for some reason, as far as i know both recv() and recvfrom() are blocking right?? Then why the difference. Does it have something to do with the functions or just the nature of TCP,UDP(which i guess is not a reason)??

P.S. Please help me understand this guys, I'm a newbie to socket programming and networking. EDIT: full server program for both TCP and UDP UDP server (with recvfrom() )

 int i=0;
   int sockfd,n;
   struct sockaddr_in servaddr,cliaddr;
   socklen_t len;
   char mesg[1024];
   sockfd=socket(AF_INET,SOCK_DGRAM,0);
   bzero(&servaddr,sizeof(servaddr));
   servaddr.sin_family = AF_INET;
   servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
   servaddr.sin_port=htons(32000);
   bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
   ofstream myfile;
  // fcntl(sockfd,F_SETFL,O_NONBLOCK);
   myfile.open("2gb",ios::out);

    while((n = recvfrom(sockfd,mesg,1024,0,(struct sockaddr *)&cliaddr,&len))>0)
    myfile.write(mesg,n);

TCP (recv() ) server program

    struct sockaddr_in socketInfo;
   char sysHost[MAXHOSTNAME+1];  // Hostname of this computer we are running on
   struct hostent *hPtr;
   int socketHandle;
   int portNumber = 8070;
   //queue<char*> my_queue;
   bzero(&socketInfo, sizeof(sockaddr_in));  // Clear structure memory
   gethostname(sysHost, MAXHOSTNAME);  // Get the name of this computer we are running on
   if((hPtr = gethostbyname(sysHost)) == NULL)
   {
      cerr << "System hostname misconfigured." << endl;
      exit(EXIT_FAILURE);
   }
   if((socketHandle = socket(AF_INET, SOCK_STREAM, 0)) < 0)
   {
      close(socketHandle);
      exit(EXIT_FAILURE);
   }
  // std::cout<<"hi starting server";
   socklen_t optlen;
   int rcvbuff=262144;
  optlen = sizeof(rcvbuff);
   socketInfo.sin_family = AF_INET;
   socketInfo.sin_addr.s_addr = htonl(INADDR_ANY); 
   socketInfo.sin_port = htons(portNumber);      // Set port number
   if( bind(socketHandle, (struct sockaddr *) &socketInfo, sizeof(socketInfo)) < 0)
   {
      close(socketHandle);
      perror("bind");
      exit(EXIT_FAILURE);
   }
   listen(socketHandle, 1);
   int socketConnection;
   if( (socketConnection = accept(socketHandle, NULL, NULL)) < 0)
   {
      exit(EXIT_FAILURE);
   }
   close(socketHandle);
time_start(boost::posix_time::microsec_clock::local_time());
   int rc = 0;  // Actual number of bytes read
   int count=0;
   char *buff;
   int a=100000;
   buff=new char[a];


   ofstream myfile;
   myfile.open("345kb.doc",ios::out|ios::app);
   if(myfile.is_open())
   {
    long i=0;
   while((count = recv(socketConnection, buff, 100000, 0))>0)
   {


    myfile.write(buff,count);

    }}
2
maybe in recvfrom you are trying to recv to much, and since you are not sure to receive everything your loop block. Or maybe you have a problem with the rest of your code - Alexis
@Alexis I'm sorry i didnt quite get that, can you please explain more? - stranger
Have you tried your udp exemple with a small buffer (20 or something around that) ? (the @you is not working :/) - Alexis
Yes recv() and recvfrom() are blocking (except with a non-blocking socket). We will need more informations about your code and how your sockets was created and multiplexed. - nouney
yes ive tried with smaller values it has the same problem it doesnt look like a problem with a size, because if recvfrom is called twice for some data which can be received with the first call itself, then the second call still blocks. - stranger

2 Answers

3
votes

the function recv() just waits untill the whole data comes and exits the loop when it is no more receiving any data

recv() on a TCP connection returns 0 when the sending side has closed the connection and this is the condition for your loop to terminate.

for a UDP program the recvfrom() function just blocks and does not exit the loop for some reason,

Because UDP is a connection-less protocol hence there is no special return code from recv() for a closed UDP connection. Unless someone sends you a 0-length datagram.

1
votes

recv() will end the loop because at the other side the socket is closed, so recv() will return 0 (socket gracefully closed) whereas, recvfrom that does not have that signal, it does not know about closing, because it's an unconnected socket. It's stay there until it receives a packet or timeout, with UDP you need a way to tell that the communication is over (finish).