[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [linrad] Second operator



Hi Lief,

It is nice to see Linrad starting to leverage multiprocessing over a
network. The word "cluster" comes to mind!

You may want to use UDP sockets instead since they do not need to have a
connection established. I have done something similar to what you have
described. The difference is that I broadcast packets with the raw PCM
data over the local area network and let the client PCs take care of the
Fourier transforms. Using the broadcast address, all computers on the
same LAN can hear the same packet. Since no connection is involved, there
is no guarantee that the data will be delivered, but if the traffic on the
LAN is low, this is rarely a problem. What I do to detect packet loss is
to reserve the first byte of every data packet for a counter that is
incremented by one on every packet sent. The receiver can keep track of
this and signal any packet loss. If the traffic is high and there is
packet loss with conventional half-duplex Ethernet hubs, you can solve the
problem by using a full-duplex Ethernet switch.

The code below is a simple example. You will need to use select() or
poll() system calls and have the sockets set for non-blocking in order to
multiplex the network code with the other processing in your code. Or
better yet, use multi-threading.

The example below uses a one-way only communication. If you need two-way
communication, you will need to mix the server and client codes, but in
this case the clients should not use broadcast, but the specific address
of the server.

Don't hesitate to comment.

73,

-- Edson, pu1jte, n1vtn, 7n4ncl

/**************************** UDP Server *****************************/
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>

#define BROADCAST_PORT     1500

int main(int argc, char *argv[]) 
{  
   int sd, rc, i;
   struct sockaddr_in cliAddr, broadcastAddr;
   struct hostent *h;
   int one = 1;
   char *data = "abcde1234567890";
   char *bcastIP = "192.168.1.255";
   
   broadcastAddr.sin_family = AF_INET;
   broadcastAddr.sin_addr.s_addr = inet_addr( bcastIP );
   broadcastAddr.sin_port = htons( BROADCAST_PORT );
   
   sd = socket( AF_INET, SOCK_DGRAM, 0 );
   if( sd < 0 ) 
   {
      perror("%s: cannot open socket");
      exit(1);
   }

   rc = setsockopt( sd, SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof(one));
   if( rc < 0 ) 
   {
      perror("setsockopt");
      exit(1);
   }

   rc = sendto( sd, data, strlen(data), 0, (struct sockaddr *) &broadcastAddr, sizeof(broadcastAddr));
   if( rc < 0 ) 
   {
      perror("sendto");
      close( sd );
      exit(1);
   }

   printf("%s: sending data to '%s'\n", argv[0], bcastIP );

   return 1;
}

/**************************** UDP Client *****************************/
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>

#define LOCAL_SERVER_PORT 1500
#define MAX_LEN           8000

int main(int argc, char *argv[]) {
  
   int sd, rc, n, i, srvLen;
   struct sockaddr_in cliAddr, srvAddr;
   char msg[MAX_LEN];
   int x;
   
   sd=socket(AF_INET, SOCK_DGRAM, 0);
   if( sd < 0 ) 
   {
      printf("%s: cannot open socket \n", argv[0] );
      exit(1);
   }

   cliAddr.sin_family = AF_INET;
   cliAddr.sin_addr.s_addr = htonl(INADDR_ANY);
   cliAddr.sin_port = htons(LOCAL_SERVER_PORT);
   rc = bind (sd, (struct sockaddr *) &cliAddr,sizeof(cliAddr));
   if( rc < 0 ) 
   {
      perror("bind: Bind failed");
      exit(1);
   }

   printf("%s: waiting for data on UDP port #%u\n", argv[0], LOCAL_SERVER_PORT);
   
   while(1) 
   {      
      /* clear buffer */
      memset( msg, 0x0, MAX_LEN );

      /* receive message */
      srvLen = sizeof(srvAddr);
      n = recvfrom(sd, msg, MAX_LEN, 0, (struct sockaddr *) &srvAddr, &srvLen);      
      if( n < 0) 
      {
	 perror("recvfrom");
	 continue;
      }
      
      /* print received message */
      printf("%s: from %s: %d bytes \n", argv[0], inet_ntoa( srvAddr.sin_addr ), n );
      
      printf("Mesg: ");
      for ( i = 0; i < n; i++ )
	 printf( "%02x ", msg[i] );
      printf("\n");
   }
   return 0;
}


On Sun, 23 Mar 2003, Leif Åsbrink wrote:

> Hi All,
> 
> To allow for a second operator on the same radio hardware I 
> have added a network to Linrad. This seems to work fine if
> computers are fast enough.
> 
> I have a primary computer, 600MHz PIII and a second computer
> 200MHz Pentium MMX. I can run with a sampling speed of up
> to 32 kHz for two channels when sending compleded transforms
> over the network. The slow computer seems to spend most of its
> time with network overhead.
> 
> I have started from the network routines of W3SZ, Roger, and I
> have no previous experience in networks whatsoever.
> 
> The network parameters are AF_INET and SOCK_STREAM which I think
> means Internet protocol (???)
> 
> The primary computer only sends data blindly while the second
> computer just receives data. There is some "magic" going on
> in the protocol that makes the other computer exit from linrad
> with a message "broken pipe" if one exits from Linrad in the
> other computer.
> 
> Are there better protocols? There is no need for the primary 
> computer to know if the listener is there. Would also be fine 
> with a protocol that would allow any number of secondary 
> computers in parallel.
> 
> Any comments?
> 
> 73
> 
> Leif
> 
> 
> 
LINRADDARNIL
d