LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Socket - problem at recvfrom function (https://www.linuxquestions.org/questions/programming-9/socket-problem-at-recvfrom-function-845871/)

fneves 11-22-2010 02:36 PM

Socket - problem at recvfrom function
 
#
Hi.
I'm doing a program where basically I want inside the while loop information is sent only at certain moments and is always listening to new information. My problem is that the function to read the buffer is blocking me the while. I've tried some solutions here in the forum as:

int flags = fcntl(sock, F_GETFL);
flags |= O_NONBLOCK;
fcntl(sock, F_SETFL, flags);

However, I am not succeeding. This is my code. What should I change it (and how)?

/*
** talker.c -- a datagram "client" demo
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define SERVERPORT 4950 // the port users will be connecting to


#define MAXBUFLEN 100

#include <time.h>
#include <iostream>
#include <list>
#include <fstream>



#include <fcntl.h>




typedef struct
{
int id;
int send_time; //send time
int ACK;
int recv_time; //receive time
} myPacket;

int main(int argc, char *argv[])
{
using namespace std;

int sockfd;
struct sockaddr_in their_addr; // connector's address information
struct hostent *he;
int numbytes;
int ID=1;

time_t init;
socklen_t addr_len;

myPacket packet;
unsigned char buffer[sizeof(packet)];

time_t epoch_time;
epoch_time = time( NULL ); //time in seconds (since 1 Jan 1970)
init=epoch_time+5;

list<myPacket> packets; //list of packets
list<myPacket>::iterator it;

ofstream success;
ofstream dropped;
success.open ("Success.txt");
dropped.open ("Dropped.txt");



int flags = fcntl(sockfd, F_GETFL);
flags |= O_NONBLOCK;
fcntl(sockfd, F_SETFL, flags);




if ((he=gethostbyname(argv[1])) == NULL) // get the host info
{
herror("gethostbyname");
exit(1);
}

if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("socket");
exit(1);
}

their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons(SERVERPORT); // short, network byte order
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);


while(1)
{
sleep (1); //1 while making every second
cout << init << endl;
cout << epoch_time << endl;

epoch_time=time(NULL); //updating time
if (init==epoch_time)
{
//packet initialization
packet.id=ID;
packet.send_time=epoch_time;
packet.ACK=0;
packet.recv_time=0;

packets.push_back (packet); //put the packet in the list

ID++;

memcpy(&buffer, &packet, sizeof(packet));

if ((numbytes=sendto(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&their_addr, sizeof their_addr)) == -1)
{
perror ("sendto");
exit(1);
}

printf("sent %d bytes to %s\n", numbytes, inet_ntoa(their_addr.sin_addr));

init=epoch_time+5;
}

flags |= O_NONBLOCK;
fcntl(sockfd, F_SETFL, flags);
// if (buffer[0] != 0xff)
// {
addr_len = sizeof their_addr;
if ((numbytes = recvfrom(sockfd, buffer, MAXBUFLEN-1 , 0, (struct sockaddr *)&their_addr, &addr_len)) == -1)
{
perror ("recvfrom");
exit(1);
}

buffer[numbytes] = '\0';
memcpy(&packet, &buffer, sizeof(buffer));

epoch_time = time( NULL );
packet.recv_time=epoch_time;

for (it=packets.begin(); it != packets.end(); it++)
{
if ((packet.recv_time - it->send_time)<10 && it->id==packet.id)
{
success << "Package " << packet.id << " was successfully received (delay = " << packet.recv_time - it->send_time << ")\n" << endl;
packets.erase(it); //apaga o pacote da lista
break;
}
if ((packet.recv_time - it->send_time)>=10 && it->id==packet.id)
{
dropped << "Package " << packet.id << " was dropped (delay = " << packet.recv_time - it->send_time << ")\n" << endl;
packets.erase(it); //apaga o pacote da lista
break;
}
}

printf("packet contains ID %.2d\n",packet.id);
printf("packet contains ACK %.2d\n",packet.ACK);
// }

if (ID==10)
{
success.close();
dropped.close();
}

}
close(sockfd);

return 0;
}

JohnGraham 11-22-2010 04:24 PM

Quote:

Code:

int flags = fcntl(sockfd, F_GETFL);
flags |= O_NONBLOCK;
fcntl(sockfd, F_SETFL, flags);

if ((he=gethostbyname(argv[1])) == NULL) // get the host info
{
    herror("gethostbyname");
    exit(1);
}

if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
    perror("socket");
    exit(1);
}


Note that you can use code tags (the #-button just above the text box you write your post in) to make code much easier to read.

Also, you should only use fcntl on a valid file descriptor.

Also, you can use SOCK_NONBLOCK like this when you open the socket to get what you want without having to clutter your code with fnctl code:

Code:

sockfd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0)

fneves 11-23-2010 09:26 AM

Hi. Many thanks for your reply. I have another problem now. My two ifs (when I print and keep the package well received in a text file based on the delay), in the first packages work well, but from the pack 4 or 5 (depends) fails to enter into this if (successes). Another problem is that packets never enter the second if.

Another problem I see that once worked well (with the blocking prints "1") and now it didnt't work, is the variable ACK coming from the server with "0". Why?

I don't know where I can put the #, but the code that I implemented is (sorry for the tags)

Many thanks again.

Quote:

/*
** talker.c -- a datagram "client" demo
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define SERVERPORT 4950 // the port users will be connecting to


#define MAXBUFLEN 100

#include <time.h>
#include <iostream>
#include <list>
#include <fstream>


typedef struct
{
int id;
int send_time; //send time
int ACK;
int recv_time; //receive time
} myPacket;

int main(int argc, char *argv[])
{
using namespace std;

int sockfd;
struct sockaddr_in their_addr; // connector's address information
struct hostent *he;
int numbytes;
int ID=1;

time_t init;
socklen_t addr_len;

myPacket packet;
unsigned char buffer[sizeof(packet)];

time_t epoch_time;
epoch_time = time( NULL ); //time in seconds (since 1 Jan 1970)
init=epoch_time+5;

list<myPacket> packets; //list of packets
list<myPacket>::iterator it;

ofstream success;
ofstream dropped;
success.open ("Success.txt");
dropped.open ("Dropped.txt");


if ((he=gethostbyname(argv[1])) == NULL) // get the host info
{
herror("gethostbyname");
exit(1);
}

if ((sockfd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0)) == -1)
{
perror("socket");
exit(1);
}

their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons(SERVERPORT); // short, network byte order
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);


while(1)
{
//sleep (1); //1 while making every second
cout << init << endl;
cout << epoch_time << endl;

epoch_time=time(NULL); //updating time
if (init==epoch_time)
{
//packet initialization
packet.id=ID;
packet.send_time=epoch_time;
packet.ACK=0;
packet.recv_time=0;

packets.push_back (packet); //put the packet in the list

ID++;

memcpy(&buffer, &packet, sizeof(packet));

if ((numbytes=sendto(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&their_addr, sizeof their_addr)) == -1)
{
perror ("sendto");
exit(1);
}

printf("sent %d bytes to %s\n", numbytes, inet_ntoa(their_addr.sin_addr));

init=epoch_time+5;
}


addr_len = sizeof their_addr;
if ((numbytes = recvfrom(sockfd, buffer, MAXBUFLEN-1 , 0, (struct sockaddr *)&their_addr, &addr_len)) != -1)
{
buffer[numbytes] = '\0';
memcpy(&packet, &buffer, sizeof(buffer));

epoch_time = time( NULL );
packet.recv_time=epoch_time;

for (it=packets.begin(); it != packets.end(); it++)
{
if ((packet.recv_time - it->send_time)<8 && it->id==packet.id)
{
success << "Package " << packet.id << " was successfully received (delay = " << packet.recv_time - it->send_time << "s)\n" << endl;
printf("packet contains ID %.2d\n",it->id);
printf("packet contains ACK %.2d\n",it->ACK);
packets.erase(it); //apaga o pacote da lista
break;
}
if ((packet.recv_time - it->send_time)>=8 && it->id==packet.id)
{
dropped << "Package " << packet.id << " was dropped (delay = " << packet.recv_time - it->send_time << "s)\n" << endl;
packets.erase(it); //apaga o pacote da lista
break;
}
}

}

if (ID==7)
{
success.close();
dropped.close();
}

}
close(sockfd);

return 0;
}






/*
** listener.c -- a datagram sockets "server" demo
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define MYPORT 4950 // the port users will be connecting to

#define MAXBUFLEN 100

typedef struct
{
int id;
int send_time; //send time
int ACK;
int recv_time; //receive time
} myPacket;

int main(void)
{
int sockfd;
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
socklen_t addr_len;
int numbytes;

myPacket packet;
unsigned char buf[sizeof(packet)];

if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("socket");
exit(1);
}

my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(MYPORT); // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero);

if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) == -1)
{
perror("bind");
exit(1);
}


while (1)
{
sleep(8);
addr_len = sizeof their_addr;
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0, (struct sockaddr *)&their_addr, &addr_len)) == -1)
{
perror("recvfrom");
exit(1);
}

printf("got packet from %s\n",inet_ntoa(their_addr.sin_addr));
printf("packet is %d bytes long\n",numbytes);
buf[numbytes] = '\0';
memcpy(&packet, &buf, sizeof(buf));
printf("packet contains %.2d\n",packet.id);

packet.ACK=1; //guarda a informação do tempo de quando chega o pedido do client

memcpy(&buf, &packet, sizeof(packet));

if ((numbytes = sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&their_addr, sizeof their_addr)) == -1)
{
perror ("sendto");
exit(1);
}
}


close(sockfd);

return 0;
}


All times are GMT -5. The time now is 11:23 AM.