C Board  

Go Back   C Board > General Programming Boards > Networking/Device Communication

Reply
 
LinkBack Thread Tools Display Modes
Old 08-21-2009, 03:42 PM   #1
Registered User
 
Join Date: Aug 2008
Posts: 23
UDP receiver not receiving packets

Hi, I have 2 programs; UDP sender and receiver. These programs are absolutely basic, trying to get the concept and understand how it works. I specify the target IP and port via arguments in the sender, in the receiver I only specify the port number. The sender sends a message and waits for an ACK then exits. The receiver waits on recvfrom() and I do not understand why. I thought INADDR_ANY binded all interfaces to the program so any packet is received by it. Maybe I'm overlooking a syntax error, but I do not see why it isn't working. Here is the receiver code

Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>
#include <netdb.h>
#include <stdio.h>

void error(char *msg)
{
	perror(msg);
	exit(0);
}
		
int main(int argc, char *argv[])
{
	int sock, length, fromlen, n;
	struct sockaddr_in server;
	struct sockaddr_in from;
	char buf[1024];
	
	if (argc < 2) 
	{
		fprintf(stderr, "ERROR, no port provided\n");
		exit(0);
	}
	
	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0) error("Opening socket");

	length = sizeof(server);
	bzero(&server,length);
	
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = INADDR_ANY;
	server.sin_port = htons(atoi(argv[1]));
	
	if ( bind(sock,(struct sockaddr *) &server,length) < 0 ) 
		error("binding");

	fromlen = sizeof(struct sockaddr_in);
	printf("Waiting to recv.\n"); fflush(stdout);

	while (1) 
        {
		n = recvfrom(sock, buf, 1024, 0, (struct sockaddr *) &from, &fromlen);
		if (n < 0) error("recvfrom");
			
		printf("Received a datagram.\n"); fflush(stdout);
		printf("%s\n", buf); fflush(stdout);

		n = sendto(sock, "Got your message\n", 17, 0, (struct sockaddr *) &from, fromlen);
		if (n  < 0) error("sendto");
	} // while

	return(1);
 } // main
Thanks for helping me debug!
Chris
chris24300 is offline   Reply With Quote
Old 08-21-2009, 05:00 PM   #2
subminimalist
 
MK27's Avatar
 
Join Date: Jul 2008
Location: NYC
Posts: 3,946
Quote:
Originally Posted by chris24300 View Post
The receiver waits on recvfrom() and I do not understand why. I thought INADDR_ANY binded all interfaces to the program so any packet is received by it. Maybe I'm overlooking a syntax error, but I do not see why it isn't working.
Using INADDR_ANY is fine, the problem is, you have not connect()ed anything. The precedure for the server is: bind a socket and wait for incoming connections using accept(); for the client: create a socket and call the server using connect().

Your "sender/receiver" terminology covers up this misconception. With IP networking, they are called SERVER and CLIENT. Both of them can send() and recv(), but the client must initiate the relationship to the server. The server cannot initiate relationships (except with other servers) because a client cannot be connected to. A client connects, ie, the CLIENT must call a SERVER.
__________________

Accuracy and integrity mean nothing if you don't make it past the censors...PYTHAGORAS

Last edited by MK27; 08-21-2009 at 05:05 PM.
MK27 is online now   Reply With Quote
Old 08-22-2009, 01:41 PM   #3
Registered User
 
Join Date: Mar 2007
Posts: 69
I think the whole point of UDP sockets is that you don't need to cennect(), listen() or accept() anything. Just bind() and then recvfrom().

Maybe there's a problem with the client.
idelovski is offline   Reply With Quote
Old 08-22-2009, 03:38 PM   #4
and the hat of vanishing
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,214
> Thanks for helping me debug!
Grab wireshark, so you can see what's going on along the wires.
If you're not sure if anything is being sent, this will tell you.
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
Up to 8Mb PlusNet broadband from only £5.99 a month!
Salem is offline   Reply With Quote
Old 08-23-2009, 08:28 AM   #5
subminimalist
 
MK27's Avatar
 
Join Date: Jul 2008
Location: NYC
Posts: 3,946
Quote:
Originally Posted by idelovski View Post
I think the whole point of UDP sockets is that you don't need to cennect(), listen() or accept() anything. Just bind() and then recvfrom().
Ah. Correct you are! I've only done stuff with TCP and thought all IP stuff was the same in this sense.

Sorry.
__________________

Accuracy and integrity mean nothing if you don't make it past the censors...PYTHAGORAS
MK27 is online now   Reply With Quote
Old 08-23-2009, 10:02 AM   #6
Registered User
 
Join Date: Aug 2008
Posts: 23
@Salem: Thanks, I didn't think of that. I don't have the time but I'll check it out tomorrow morning and see what's being sent.

idelovski, you mentioned there could be a problem with the client. When I compile I get two warnings:

client_udp.c:52: warning: passing argument 5 of ‘sendto’ from incompatible pointer type
client_udp.c:58: warning: passing argument 5 of ‘recvfrom’ from incompatible pointer type

since the code satisfies the arguments in the man page I figured it wouldn't matter... It might, here is the client code.

Code:
void error(char *msg)
{
	perror(msg);
	exit(0);
} // error

int main(int argc, char *argv[])
{
	int sock, length, n;
	struct sockaddr_in server, from;
	struct hostent *hp;
	char buffer[256];
	
	if (argc != 3) 
	{ 
		printf("Usage: client <server IP> <port>\n");
		exit(1);
	}

	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0) 
		error("socket");
	
	///////////////////////////////////////
	/* Specify Socket Info */
	server.sin_family = AF_INET;			
	server.sin_port = htons(atoi(argv[2]));		// port
	server.sin_addr.s_addr = inet_addr(argv[1]);	// ip
	///////////////////////////////////////
	
	length = sizeof(struct sockaddr_in);

	printf("Please enter the message: ");
	bzero(buffer, 256);
	fgets(buffer, 255, stdin);

	n = sendto(sock, buffer, strlen(buffer), 0, &server, length);
	if (n < 0) 
		error("Sendto");

	printf("\nSent the message, waiting for response.\n"); fflush(stdout); 

	n = recvfrom(sock, buffer, 256, 0, &from, &length);
	if (n < 0) 
		error("recvfrom");

	printf("Got an ACK: %s", buffer); fflush(stdout); 
} // main
chris24300 is offline   Reply With Quote
Old 08-23-2009, 11:55 AM   #7
Registered User
 
Join Date: Mar 2007
Posts: 69
Well, the code as it is works on my Mac.

I had to include <stdlib.h> for the exit() and changed length type from int to socklen_t and I've put casts to (struct sockaddr *) to suppress those warnings, but aside from that, it all went well.

$ ./srv 1234 &
[1] 382
$ Waiting to recv.

$ ./clnt 127.0.0.1 1234
Please enter the message: hallo

Sent the message, waiting for response.
Received a datagram.
hallo

Got an ACK: Got your message
idelovski is offline   Reply With Quote
Old 08-23-2009, 09:06 PM   #8
int x = *((int *) NULL);
 
Cactus_Hugger's Avatar
 
Join Date: Jul 2003
Location: Banks of the River Styx
Posts: 891
The use of (struct sockaddr *) is what you're supposed to do.

Your networking code, more or less, is fine. Your use of buffers... your server has a buffer overflow, and I suspect you have gaps in your knowledge regarding buffers, etc. Take this:
Code:
         n = recvfrom(sock, buf, 1024, 0, (struct sockaddr *) &from, &fromlen);
         if (n < 0) error("recvfrom");
 
         printf("Received a datagram.\n"); fflush(stdout);
         printf("%s\n", buf); fflush(stdout);
When you recvfrom() a buffer, the return value, n here, is - on success - the number of bytes recv'd. You ignore this, and send that buffer to printf(). printf() excepts a string and specifically, a string should be null-terminated. recvfrom(), since it doesn't work with strings, doesn't guarentee that buf is null-terminated. Thus, you possibly cause buffer overflows when you pass this buffer to printf(), if the sender doesn't send a trailing null. (And worse, looking at your client code - you don't!)

In short: Make sure your buffer is null terminated.
The general form is this, if you want a string:
Code:
n = recvfrom(sock, buf, SIZE_OF_BUFFER - 1, 0, .....);
// check n for errors
buf[n] = 0; // null terminate that buffer.
printf("%s\n", buf);
This also worries me:
Code:
     printf("Please enter the message: ");
     bzero(buffer, 256);
     fgets(buffer, 255, stdin);
There is no real reason to call bzero() here. Further, your buffer sizes to bzero() and fgets() differ. If you real the man pages for both functions, you'll see that bzero() just zeros an area, and that fgets will put in a trailing null, so you can pass 256 to both functions.
__________________
long time; /* know C? */
Unprecedented performance: Nothing ever ran this slow before.
Any sufficiently advanced bug is indistinguishable from a feature.
Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
The best way to accelerate an IBM is at 9.8 m/s/s.
recursion (re - cur' - zhun) n. 1. (see recursion)
Cactus_Hugger is offline   Reply With Quote
Old 08-24-2009, 08:25 AM   #9
Registered User
 
Join Date: Aug 2008
Posts: 23
Thanks for all the responses! I'm still getting 'broken in' to linux and network programming, so please bare with me.

When I run on lo (127.0.0.1) everything works fine. It's when I use different machines that the packet is lost somewhere.

I am completely new to wireshark so I'll post what I think it beneficial. First off, I can ping both addresses and I can see the ICMP protocol is the only protocol that successfully reaches the destination. When I was capturing while running my programs I only get one captured message, i'll format as close as possible
Code:
No.    Time      Source         Destination      Protocol      Info
1     0.000      10.0.0.X        10.0.0.X          UDP         Source port: 33267 Destination port: search-agent
#      1947.3    10.0.0.X        10.0.0.X         ICMP         Echo (ping) reply
I don't know what the UDP info means, is it searching for the port/host? The addresses are 2 devices that can communicate between one another over the air, they are not the IP of my machines. Not sure what to do now... Can I send messages in IMCP?

Thanks,
Chris

Last edited by chris24300; 08-24-2009 at 09:59 AM.
chris24300 is offline   Reply With Quote
Old 08-24-2009, 10:30 AM   #10
and the hat of vanishing
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,214
TCP and UDP (what you asked for with SOCK_DGRAM) are the two common data transport protocols.
ICMP is one of the many control protocols which enable the whole shebang to work.

> It's when I use different machines that the packet is lost somewhere.
Check your various firewall logs to see if requests are being blocked.
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
Up to 8Mb PlusNet broadband from only £5.99 a month!
Salem is offline   Reply With Quote
Old 08-24-2009, 11:47 AM   #11
Registered User
 
Join Date: Mar 2007
Posts: 69
Try with port 7. It is echo port and should be allowed.
idelovski is offline   Reply With Quote
Old 08-24-2009, 02:14 PM   #12
Registered User
 
Join Date: Aug 2008
Posts: 23
How many logs are there? I only know of the log in /var/log/messages. I just tried a sample send/receive UDP(straight from a book) using my actual machines, not external devices. The results were the same, nothing. So I should have started from step 1.

I'm about to check through the router, but if the problem does not lie there then what else can cause this blockage? I started reading on the iptables so that's where I'm looking next. Are there other programs I should look at also?
chris24300 is offline   Reply With Quote
Old 08-24-2009, 03:13 PM   #13
Registered User
 
Join Date: Aug 2008
Posts: 23
OK now i'm really confused. I changed which computers I used as the sender/receiver and everything works perfect....
chris24300 is offline   Reply With Quote
Old 08-24-2009, 06:01 PM   #14
subminimalist
 
MK27's Avatar
 
Join Date: Jul 2008
Location: NYC
Posts: 3,946
Quote:
Originally Posted by chris24300 View Post
OK now i'm really confused. I changed which computers I used as the sender/receiver and everything works perfect....
Were you using LAN addresses (192.168...) or live inet addresses? Getting to a computer connected to a router "as if it were a server" *might* not be as simple as using the assigned IP address.
__________________

Accuracy and integrity mean nothing if you don't make it past the censors...PYTHAGORAS
MK27 is online now   Reply With Quote
Old 08-27-2009, 08:56 AM   #15
Registered User
 
Join Date: Aug 2008
Posts: 23
No, i used both the device IP (10.0.0.X) and my actual computer IPs. For some reason the destination port is lost when I'm on that specific machine as shown in my wireshark post previously.
chris24300 is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Need help with UDP AlexS C# Programming 0 07-07-2009 06:21 PM
Sending / Receiving Info Via TCP or UDP bengreenwood C Programming 0 03-24-2009 02:17 AM
simultaneously waiting for data on FIFO and UDP using select call yogesh3073 Networking/Device Communication 2 01-05-2007 09:53 AM
UDP and TCP packets on port 6112 biosninja A Brief History of Cprogramming.com 7 01-19-2004 11:21 AM


All times are GMT -6. The time now is 01:41 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22