tags:

views:

762

answers:

3

I discovered a nice abstraction whereby I can read in data from UDP using a FILE. This works great for reading in data, but I cannot get it to work for spitting out data over UDP. Here is the code for reading in the UDP data over a FILE stream:

u_int8 *buf;
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in serverAddr;
if (sockfd < 0) {
  printf("Could not open socket\n");
  exit(1);
}
buf = malloc(BUF_SIZE * sizeof(u_int8));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr.sin_port = htons(port);
int rc = bind(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
if (rc<0) {
  printf("Could not bind to port %d\n", port);
  exit(1);
}
/* Make sockfd blocking */
int flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK);

FILE *sockfile;
sockfile = (FILE*)fdopen(sockfd, "r");

Now some other code can call:

fread(data, sizeof(u_int8), frame_payload_size, sockfile);

This works fine. However, the reverse doesn't seem to:

u_int8 *buf;
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in clientAddr;
if (sockfd < 0) {
  printf("Could not open socket\n");
  exit(1);
}
memset((char *)&clientAddr, 0, sizeof(clientAddr));
buf = malloc(BUF_SIZE * sizeof(u_int8));
clientAddr.sin_family = AF_INET;
clientAddr.sin_port = htons(port);
if (inet_aton("127.0.0.1", &clientAddr.sin_addr)==0) {
  printf("inet_aton()\n");
  abort();
}
int rc = bind(sockfd, (struct sockaddr *)&clientAddr, sizeof(clientAddr));
FILE *sockfile;
sockfile = (FILE*)fdopen(sockfd, "w");

Some other code will call:

written = fwrite(fm->frame, sizeof(u_int8), fm->frame_length, data_out_stream);

'written' will return a positive number of elements written, yet no UDP packets seem to be generated.

Is what I am trying to do possible? Any suggestions as to why it might not be working?

+1  A: 

You are not hiding information, which might be cool, but you are giving false information to the other piece of code, ie that your socket behaves like a stream. I think you should stick with read / write call, or you will find yourself with a leaky abstraction

shodanex
A: 

Flush the FILE. Network packets are only generated when they are full or when you force a flush. So unless you write more than 1500 bytes (the default, including header fields), the computer will wait with the delivery.

Aaron Digulla
+1  A: 

This is actually pretty weird. Use fflush(), or better yet, use send() instead of fwrite() and ditch the FILE. You will encounter unexpected behavior due to the semantics of how FILE objects are buffered and how datagrams are not guaranteed to arrive in order / arrive at all, this can result in garbled messages. Unless you're using UNIX sockets.

Dietrich Epp