wiki:Docs/Prog/Manual/DeviceSupport/Network

Version 12 (modified by travis_l, 14 years ago) ( diff )

--

Network

Network File System (NFS)

It is helpful to setup an NFS share on your host computer for application testing. You may place your executables to be tested in the directory and access them from the target hardware. Using PuTTY, MiniCom, HyperTerminal or another communications program to communicate with the debug serial port 115000 8N1 the prompt should appear as:

#

Type:

# mount –t nfs 192.168.1.100:/srv/nfs /mnt/nfs –o nolock <CR>

Replace "192.168.1.100:/srv/nfs" with the appropriate IP address and share name of your NFS share. "/srv/nfs" is NFS share name already configured when using the VMware development image.

Type:

# cd /mnt/nfs

to change to the NFS directory. You can then run an application directly from the NFS folder without having to copy it to the 825 NAND. Make sure the application is flagged as executable from the host. To set a file as executable:

# chmod +x indicator

To run the application type:

# ./indicator &

To run an application named indicator. Note the "./" at the beggining is needed to tell the OS to run the executable in the current directory. Alternatively, you may run the executable file by specifying the full path:

# /mnt/nfs/indicator &

The "&" symbol specifies that the application will run in a new thread so you may continue to type commands, for example to check memory or copy files while the program is running. If the "&" symbol is not specified the terminal will be locked until the program exits or "CTRL-C" from the terminal will usually be able to stop the execution.

To stop a running application type:

# ps

This will list the running processes:

  PID TTY          TIME CMD
    1 ?        00:00:02 init
    2 ?        00:00:00 kthreadd
    3 ?        00:00:00 migration/0
    4 ?        00:00:00 ksoftirqd/0
    5 ?        00:00:00 watchdog/0
    6 ?        00:00:00 migration/1
    7 ?        00:00:00 ksoftirqd/1
    8 ?        00:00:00 watchdog/1
    9 ?        00:00:00 events/0
   10 ?        00:00:00 events/1
   11 ?        00:00:00 khelper
   85 ?        00:00:00 kintegrityd/0
   86 ?        00:00:00 kintegrityd/1
   88 ?        00:00:00 kblockd/0
   89 ?        00:00:00 kblockd/1
   91 ?        00:00:00 kacpid
   92 ?        00:00:00 kacpi_notify

Identify the PID number of the process to stop and type:

# kill <PID>  (where <PID> is the appropriate process ID)

The "pidof" statement allows for another method of stopping a process:

# kill 'pidof indicator'

Note if you accidentally press ENTER before closing the apostrophe you may get a prompt:

>

It is not possible to get out of this prompt until a closing apostrophe "'" is typed and ENTER is pressed:

>'
Unknown command
#

At times you may lose track of your current path. To check the current path type:

# pwd

This will respond with the current path such as “/mnt/nfs”.

Weight Server -- Network Access

The 825 weight server feature allows remote control operations to be performed via a network connection. The weight server also allows weight data to be accessed via a network connection. The weight data may be accessed using SMA commands such as "<LF>W<CR>" from a client to request the weight or the legacy CTRL-E request for 738 computer format data. This also network access to the 825 from various software such as Cardinal WinVRS or Cardinal WinDDE.

Network Programming

Programs may be written utilizing many of the common Linux network libraries. Programs may be written to act as a TCP/IP server waiting for connections from clients. This is similar to the 825 weight server.

825 TCP/IP Server Example

// TCP/IP Server Demo

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>

#include <string.h>

#include <math.h>
#include <time.h>

#include <signal.h>

#include <netinet/in.h>
#include <arpa/inet.h>

#include <sys/mman.h>
#include <sys/types.h>          /* socket, bind, accept */
#include <sys/socket.h>         /* socket, bind, accept, setsockopt, */
#include <sys/stat.h>           /* open */

#include <vector>
using namespace std;

const int BUFSIZE = 30;

// To allow for multiple-byte requests from clients we have to keep a separate receive buffer for each client
struct client_info
{
   int socket;
   char buf[BUFSIZE];
   int pos;
};

// Dynamic list to keep track of connected clients
vector<client_info> client_list;

int server_s;

const int sock_opt = 1;

const int nPort = 10010;  // Change to use a different TCP/IP port

int ServerProcess(void)
{
   int i;
   int client_s;
   struct sockaddr_in addr;
   socklen_t socklen = sizeof(addr);

   // Check for new client connections
   client_s = accept(server_s, (sockaddr*)&addr, &socklen);
   if(client_s >= 0)
   {
      char szIP[INET_ADDRSTRLEN];
      inet_ntop(AF_INET, &addr.sin_addr, szIP, INET_ADDRSTRLEN);

      printf("TCP/IP server connection from IP %s socket %d\r\n", szIP, client_s);

      /* nonblocking socket */
      if(fcntl(client_s, F_SETFL, O_NONBLOCK) == -1)
      {
         printf("fcntl: unable to set new socket to non-block\r\n");
         close(client_s);
      }
      else
      {
         // Add client information to list of connected clients
         client_info info;
         info.socket = client_s;
         info.pos = 0;
         client_list.push_back(info);
      }
   }

   // Service any connected clients
   if(client_list.size() > 0)
   {
      struct timeval tv;
      tv.tv_sec = 0;
      tv.tv_usec = 0;

      // Load up structure for "select" statement to check for receive data from all connected clients
      fd_set rfds;
      FD_ZERO(&rfds);
      int nMaxfd = 0;
      for(i = 0; i < (int)client_list.size(); i++)
      {
         FD_SET(client_list[i].socket, &rfds);
         if(client_list[i].socket > nMaxfd)
            nMaxfd = client_list[i].socket;
      }

      int retval = select(nMaxfd + 1, &rfds, NULL, NULL, &tv);
      if(retval == -1)
      {
         printf("select return -1\r\n");
      }
      else if(retval > 0)
      {
         int rcvlen;
         char data[20], sendbuf[50];
         int z;
         int remove = -1;

         // Loop through array of all connected clients
         for(i = 0; i < (int)client_list.size(); i++)
         {
            // Select statement will have loaded rfds to identify which clients have data available to read from
            if(FD_ISSET(client_list[i].socket, &rfds))
            {
               rcvlen = recv(client_list[i].socket, data, sizeof(data), 0);
               // Loop through bytes received from this client
               for(z = 0; z < rcvlen; z++)
               {
                  // If ENTER we have completed message - otherwise add character to the client read buffer
                  if(data[z] == '\r')
                  {
                     // Must terminate the string
                     client_list[i].buf[client_list[i].pos] = '\0';
                     printf("Socket %d message [%s]\r\n", client_list[i].socket, client_list[i].buf);

                     // In this sample we check for "TIME<CR>" received and respond with the server time
                     if(!strcmp(client_list[i].buf, "TIME"))
                     {
                        // Get current time
                        time_t rawtime;
                        struct tm *timeinfo;
                        time(&rawtime);
                        timeinfo = localtime(&rawtime);

                        // Format time into string
                        sprintf(sendbuf, "Server time is: %02d:%02d:%02d ",
                           timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);

                        // Send to client
                        send(client_list[i].socket, sendbuf, strlen(sendbuf), 0);
                     }

                     // Reset the buffer position for the next request
                     client_list[i].pos = 0;
                  }
                  else
                  {
                     // Add character to buffer
                     client_list[i].buf[client_list[i].pos++] = data[z];

                     // In case of overflow reset position to prevent overwriting memory and crashing
                     if(client_list[i].pos >= BUFSIZE)
                        client_list[i].pos = 0;
                  }
               }
               if(rcvlen <= 0)
               {
                  // If the receive length is zero or negative indicates an error - we lost the connection
                  // Set variable remove to indicate this client should be removed
                  printf("recv Error %d\r\n", rcvlen);
                  remove = i;
               }
            }
         }
         if(remove >= 0)
         {
            // If a client disconnected remove it from the list
            printf("Removing %d client socket %d\r\n", remove, client_list[remove].socket);
            client_list.erase(client_list.begin() + remove);
         }
      }
   }
   return 0;
}

int main()
{
   // Create the server socket
   server_s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
   if(server_s == -1)
   {
      printf("unable to create socket\r\n");
      return -1;
   }

   // Set server socket to be nonblocking
   if(fcntl(server_s, F_SETFL, O_NONBLOCK) == -1)
   {
      printf("fcntl: unable to set server socket to nonblocking");
      return -1;
   }

   // Set server to reuse socket addresses
   if((setsockopt(server_s, SOL_SOCKET, SO_REUSEADDR, (void *) &sock_opt, sizeof (sock_opt))) == -1)
   {
      printf("setsockopt");
   }

   // Prepare sockaddr structure before binding
   struct sockaddr_in server_sockaddr;
   memset(&server_sockaddr, 0, sizeof server_sockaddr);
   server_sockaddr.sin_family = PF_INET;
   server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
   server_sockaddr.sin_port = htons(nPort);

   // Bind the socket address
   if(bind(server_s, (struct sockaddr *) &server_sockaddr, sizeof (server_sockaddr)) == -1)
   {
      printf("Unable to bind\r\n");
      return -1;
   }

   // Begin listening for clients to connect
   if(listen(server_s, 10) == -1)
   {
      printf("unable to listen");
   }

   struct timespec delaytm;
   delaytm.tv_sec = 0;
   delaytm.tv_nsec = 8000000;

   // Processing loop
   while(1)
   {
      ServerProcess();

      // Small time delay to help OS perform its processing at a smooth rate
      nanosleep(&delaytm, NULL);
   }

   return 0;
}

The server may be tested by running it on a networked 825. Use a PC connected to the network running a terminal program such as Hyperterm or CommView. Select the appropriate IP address of the indicator, and port 10010. In the terminal type TIME<CR> and the 825 server should respond with the time of the 825 indicator.

825 TCP/IP Client Example

// TCP/IP Client Example


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>


#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define CHR_STX		0x02
#define CHR_ETX		0x03

#define IP_ADDR		"90.1.2.202"
#define IP_PORT		3000

#define START_CHR	CHR_STX
#define STOP_CHR	CHR_ETX

enum RcvMode { rcvIdle, rcvData };

#define RCVMODE_IDLE	0
#define RCVMODE_DATA	1

/*
 * This example connects to the server
 * When a properly formatted message <STX>message<ETX> is received from the server
 * it is sent back to the server
 *
 */

int main()
{
	struct sockaddr_in serv_addr;
	struct hostent *svr;
	char buffer[50], rcv_buf[50];
	int sockfd, n, i, rcv_pos = 0;
	RcvMode rcvMode = rcvIdle;

	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd < 0)
	{
		printf("error\r\n");
		return -1;
	}

	svr = gethostbyname(IP_ADDR);
	if(svr == NULL)
	{
		printf("error getHostbyname\r\n");
		return -1;
	}

	memset(&serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	memcpy(&serv_addr.sin_addr.s_addr, svr->h_addr_list[0], sizeof(serv_addr.sin_addr.s_addr));

	serv_addr.sin_port = htons(IP_PORT);
	if(connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
	{
		printf("error connecting\r\n");
		return -1;
	}

        // Set the socket to be non-blocking	
	if (fcntl(sockfd, F_SETFL, O_NONBLOCK) == -1)
        {
                printf("fcntl: unable to set non-blocking\r\n");
        }

	printf("Connected to server %s port %d waiting for message from server\r\n", IP_ADDR, IP_PORT);
	while(1)
	{
		n = read(sockfd, buffer, sizeof(buffer));
		// We are not blocking. You must copy to another buffer to be sure to get a complete message
		// For example in one iteration of the loop you might receive:
		//				<STX>This is a
		// and the nest iteration of the loop may give you:
		//				test message<ETX>
		if(n > 0)
		{
			for(i = 0; i < n; i++)
			{
				if(rcvMode == rcvIdle)
				{
					if(buffer[i] == START_CHR)
					{
						rcvMode = rcvData;
					}
				}
				else
				{
					if(buffer[i] == STOP_CHR)
					{
						rcv_buf[rcv_pos] = '\0';
						printf("Message received [%s]\r\n", rcv_buf);

						// Send back the message without the <STX> and <ETX>
						send(sockfd, rcv_buf, strlen(rcv_buf), 0);

						rcv_pos = 0;
						rcvMode = rcvIdle;
					}
					else if(rcv_pos < (int)(sizeof(rcv_buf) - 1))
					{
						rcv_buf[rcv_pos++] = buffer[i];
					}
				}
			}
		}
	}
	return 0;
}


This client program may be tested by running it on a networked 825. A PC may be connected on the network running CommView in server mode. Set the port to 3000. In the CommView make a function key to output: %02This is test%03 When this function key is pressed the 825 will display "This is a test" and the message will also be sent back to the CommView server.

Top

Note: See TracWiki for help on using the wiki.