ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Hi people, not sure this is the best place to ask but I will give it a go.
I've written some code destined for an embedded system but currently running on PCs to broadcast audio around a network.
Two processes run in parallel on each PC, an encoding process called tx and a receiving process called rx.
The tx process reads audio from pulse and sends it as UDP broadcast packets about the rate of 40 packets a second.
The rx processes sets up a UDP socket, sets it to O_NONBLOCK. It then reads packets as fast as possible, each packet of audio is passed to pulse to be played. All seems to work, so far so good.
The weirdness is with the behaviour of "recvfrom". If I run the rx process first then recvfrom returns a mixture of -1 (EAGAIN) and the size of the received packet, it does not block. If I run the tx process, then start the receive process second then "recvfrom" blocks and only returns the size of packets.
For example if I print the result of "revcfrom", starting rx process first gives.
It would be helpful to see how your client (receiver) is managing the call to recv_from(), and the surrounding code around it.
Personally, I do not see the purpose of setting up a UDP socket to be non-blocking. I tend to use select() to determine if there is activity on the socket (ie something needs to be read), and if I need to perform additional duties while the socket is idle, then I specify a timeout for the select(). Handling a return value of -1 and an errno of EAGAIN in a loop doesn't seem very prudent.
I initialise the socket on the receiving process like this:
Code:
udp_setup_socket(char *myipaddress,int listen)
{
// Open socket
udpsockfd = socket(PF_INET, SOCK_DGRAM, 0);
if (udpsockfd<0)
{
perror("error, could not create socket");
exit(1);
}
printf("%s: Socket created\n",PROGNAME);
fflush(stdout);
// Setuop socket, specify listening interfaces etc
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(PORT+conversation);
recvaddr.sin_addr.s_addr = INADDR_ANY;
memset(recvaddr.sin_zero,'\0',sizeof (recvaddr.sin_zero));
// Put socket in non blcoking mode
int flags = fcntl(udpsockfd, F_GETFL); // Get the sockets flags
flags |= O_NONBLOCK; // Set NONBLOCK flag
if (fcntl(udpsockfd, F_SETFL, flags) == -1) // Write flags back
{
perror("error,fcnctl failed - could not set socket to nonblocking");
exit(1);
}
// Bind to socket, start socket listening
if (listen==TRUE)
{
if(bind(udpsockfd, (struct sockaddr*) &recvaddr, sizeof (recvaddr)) == -1)
{
perror("bind failed, only one process can bind at a time");
exit(1);
}
fprintf(stderr,"%s: Listening for UDP data on port %d \n",PROGNAME,PORT+conversation);
fflush(stderr);
}
}
and read it with this function:
Code:
// Receive a single UDP frame if available
int udp_receive (char *originating_ip, int verbose, int hexdump)
{
//struct sockaddr_in recvaddr; // An IP address record structure
int c,i;
unsigned int offs;
int numbytes;
int addr_len;
addr_len = sizeof(recvaddr);
numbytes = recvfrom (udpsockfd, udpbuffer, 1024, 0, (struct sockaddr *) &recvaddr, &addr_len);
//printf("%d ",numbytes); fflush(stdout);
if (numbytes>0)
{
sprintf(originating_ip,"%s",inet_ntoa(recvaddr.sin_addr));
if (verbose==TRUE) // If chatty is true show receipt of packets
{
printf("%s: received %d bytes from %s via UDP port %d ",PROGNAME,numbytes,originating_ip,PORT+conversation);
fflush(stdout);
}
if (hexdump==TRUE) // If dump is true show packets as hexdump
{
if (verbose==TRUE)
printf(" Dumping contents\n");
c=0; offs=0;
printf("%04X: ",offs);
for (i=0;i<numbytes;i++)
{
//printf("%c",udpbuffer[i]); // ASCII
printf("%02X ",udpbuffer[i]); // HEX
c++;
if (c==16)
{
offs=offs+16;
c=0;
printf("\n%04X: ",offs);
fflush(stdout);
}
}
printf("\n");
}
return(TRUE);
}
return(FALSE);
}
Code:
while (quit!=TRUE)
{
if (udp_receive(originating_ip,FALSE,FALSE)==TRUE)
{
process packet
What I fail to understand is why changing the order in which the processes start seems to change the blocking behaviour of recvfrom ? Why would I need to use select() to insert and extra poll before a function that should simply never block ? I guess i'm failing to understand something subtle ...
Unfortunately, I cannot glean anything from the code you presented; it looks ok. I have a few question though...
1. What is the value of 'listen' when your rx (receiver) calls upd_setup_socket()?
2. What is the value of myipaddress within udp_setup_socket()?
Quote:
Originally Posted by jonshouse
Why would I need to use select() to insert and extra poll before a function that should simply never block ? I guess i'm failing to understand something subtle ...
By default, recvfrom() blocks. If you setup the socket to be non-blocking, then it shouldn't wait to receive data. If you attempt to receive data when there isn't any to be read, then a non-blocking socket will report an error with errno set to EAGAIN (or equivalently EWOULDBLOCK).
I personally use select() to know when it is appropriate to receive on the socket. I use non-blocking setup very sparingly, and when I do, it is for a TCP socket (to mimic a stream), not a UDP socket which is used to receive whole datagrams.
I do not have enough information about your applications to determine if it is merely a speed issue, or some other subtle issue with the code. You undoubtedly must have some setup that governs how often the the rx code attempts to read using recvfrom(), otherwise I would suspect that it would flood the terminal with error messages.
I found the issue, it was nothing to do with sockets at all ! DOH !
What I thought was a blocking behaviour in recv_from() was actually a blocking behaviour in the pulse audio code causing recv_from to always have pre-buffered data available. Seems pulse audio pa_simple_write() does not block unless the audio buffers are full, then it suddenly starts to block for a long period, odd. Data is generated at the same rate it played so I don't quite understand what is going on .. ho hum ...
The "myipaddress" pointer was stale code, i've removed it :-)
The reason for a non-blocking udp socket is that 8 sources are sending 44 1k Byte packets a second, so recv_from needs to pick up 352 1k frames of data per second and well as pipe those into 8 connection to pulse audio for playback. Not a struggle for a PC but I have my doubts this going to be as simple when ported to arm and Wifi ...
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.