/* ******************************** DEMO1: 8000 TCP/IP DIO demo File name: demo1.c Compiler: Borland C++ 3.1 Compile mode: large Simple Command set for this Demo DO command #SiDDDD for 16 bit DO modules example:I-8056,I-8057 #SiDD for 8 bit DO modules example:I-8054,I-8068 # => command header S => Slot variable i => slot number DD => byte data DDDD => WORD data for example #S055AA => send the Data 0x55aa to slot 0 DI command $Si => Read DI and DO read back $ => command header S => Slot variable i => slot number for example $S1 => read the DI from slot 1 If user want to add his program just modify the function "User_Program". The Differences between iPAC-8000 library and old library are as below: 1. call GetIP,GetIP2 and etc function to get Network configuration from eeprom ,not GeSaveIP and lhip (GeSaveIP and lhip have been removed on the iPAC-8000 library ,the GetIP and etc function is defind at 8000a.h) 2.For iPAC-8000 , there is no need to deal with Ninit() and Portinit (NetStart function replaces then) ********************************* */ #include #include #include #include "..\..\..\lib\tcpip32.h" #include "..\..\..\lib\8000a.h" #define BUFSIZE 1024 /* read/write buffer size */ #define SERVICE 10000 /* define the service port for Server */ #define SOCKETS 32 /* define the maximum number of sockets */ #define QLEN SOCKETS-1 /* maximum connection queue length */ int es; /* flag to run ES (service loop) */ fd_set rfds; /* set of socket file descriptors for reading */ typedef struct socket_state { int active; /* socket is active */ int init; /* socket just initiated */ struct sockaddr_in sin; /* client address */ } socket_state; socket_state sst[SOCKETS]; /* sockets state table */ //DIODATA DIODATA; char Message1[]="connected successful."; char ErrorMessage[]="Command Error!"; //unsigned long far *TimeTicks=(unsigned long far *)0x0040006CL; int User_Program(int skt,char *buf,int cc); void killsockets(void); /************************************************************************* * killsockets * clear, shutdown, and close all sockets *************************************************************************/ void killsockets() { int i; FD_ZERO( &rfds ); /* clear FD set */ for (i = 0; i < SOCKETS; i++) { if (sst[i].active) { /* if socket lives, kill it */ shutdown( i, 0 ); closesocket( i ); } } } /************************************************************************* * do_echo * * when client is connected, do echo here or process message * Add the user process program here. *************************************************************************/ int do_echo( int skt ) { int i, cc, err=0; char buf[BUFSIZE]; if (sst[skt].init) { sst[skt].init = 0;/* socket is just initiated */ return err; } //err = cc = readsocket( skt, buf, strlen(buf)/*sizeof(buf)*/ ); err = cc = recv( skt, buf, sizeof(buf),0 );// Read Socket data buf[cc] = '\0'; if (err == 0)/* disconnected */ { shutdown( skt, 0 );//shutdown socket closesocket( skt );//close socket FD_CLR( skt, &rfds );//clear setting sst[skt].active = 0; return err; } if (err < 0)/* read error */ { shutdown( skt, 0 );//shutdown socket closesocket( skt );//close socket FD_CLR( skt, &rfds );//clear setting sst[skt].active = 0; return err; } //This send back is not necessary for every one //_____________________________________________________ err= send(skt,buf,cc,0);//echo string if(err < 0) { /* write error */ Print( "echo write error %d\n\r", err ); shutdown( skt, 0 ); closesocket( skt ); FD_CLR( skt, &rfds ); sst[skt].active = 0; return err; } //_____________________________________________________ //force to terminal this program if (!strcmp("down", buf)) { /* shutdown echo server */ es = 0; Print( "Server is Terminal\n\r"); return err; } // *************************************************************************/ err = User_Program(skt,buf,cc); // *************************************************************************/ return err; } /************************************************************************* * main * program main routine *************************************************************************/ int RxCounter=0; int RxCounterOut=0; //struct ip host_ip = { {192,168,255,2},{255,255,0,0} }; struct ip host_0 = { {192,168,0,2},{255,255,255,0}}; struct ip host_1 = { {192,168,0,3},{255,255,255,0}}; struct ip *host_ip[2]={&host_0,&host_1}; struct ip gateway_0 = { {192,168,0,1},{255,255,255,0}}; struct ip gateway_1 = { {192,168,0,1},{255,255,255,0}}; struct ip *gateway_ip[2]={&gateway_0,&gateway_1}; extern struct NETDATA *NetHost[2],*NetGateway[2]; main( int argc, char *argv[] ) { struct sockaddr_in ssin; /* client Internet endpoing address */ int sin_len; /* length of sockaddr_in */ int s; /* master socket for listenning */ int ss; /* slave socket got from accept */ int type, protocol, err=0; int rc; /* return code of selectsocket */ int i,ret,ver,SlotType; // unsigned long far *IntVectMain=(unsigned long far *)0x00000000L; struct timeval seltime; unsigned char cIP_Net[4]; unsigned char cMASK_Net[4]; unsigned char cGATEWAY_Net[4]; unsigned char cIP_Net2[4]; unsigned char cMASK_Net2[4]; unsigned char cGATEWAY_Net2[4]; Print("------------Open 8000-----------\n\r"); ver=GetLibVersion(); Print("Library version is %d.%02d\n\r",ver>>8,ver&0xff); SlotType = GetNumberOfSlot();//slot4 or slot8 Print("Current Slot Type = %d\n\r",SlotType); InitLib(); NetStart(); /*************************************** * Network Environment * ***************************************/ // call GetIP,GetIP2 and etc function to get Network configuration from eeprom (not GeSaveIP and lhip) GetIp(cIP_Net); Print("IP= %d.%d.%d.%d\n",cIP_Net[0],cIP_Net[1],cIP_Net[2],cIP_Net[3]); GetMask(cMASK_Net); Print("MASK= %d.%d.%d.%d\n",cMASK_Net[0],cMASK_Net[1],cMASK_Net[2],cMASK_Net[3]); GetGateway(cGATEWAY_Net); Print("GATEWAY= %d.%d.%d.%d\n",cGATEWAY_Net[0],cGATEWAY_Net[1],cGATEWAY_Net[2],cGATEWAY_Net[3]); GetIp2(cIP_Net2); Print("IP2= %d.%d.%d.%d\n",cIP_Net2[0],cIP_Net2[1],cIP_Net2[2],cIP_Net2[3]); GetMask2(cMASK_Net2); Print("MASK2= %d.%d.%d.%d\n",cMASK_Net2[0],cMASK_Net2[1],cMASK_Net2[2],cMASK_Net2[3]); GetGateway2(cGATEWAY_Net2); Print("GATEWAY2= %d.%d.%d.%d\n",cGATEWAY_Net2[0],cGATEWAY_Net2[1],cGATEWAY_Net2[2],cGATEWAY_Net2[3]); /* For iPAC-8000 , there is no need to deal with Ninit() and Portinit (NetStart function replace then) */ /* #if 0 err = Ninit(); if (err < 0) { Print( "Ninit() failed! error %d\n\r", err ); return err; } Print( "Ninit() Successful! \n\r"); err = Portinit( "*" ); if (err < 0) { Print( "Portinit() failed! error %d\n\r", err ); Nterm(); return err; } Print( "Portinit() Successful! \n\r"); #endif */ /************************** * allocate master socket * **************************/ type = SOCK_STREAM; /* TCP/IP */ protocol = 0; /* always 0 */ err = s = socket( PF_INET, type, protocol ); if (s < 0) { Print( "can't create socket! error %d\n\r", err ); Nterm(); return err; } Print( "create socket seccessful!\n\r"); /******************************** * addressing for master socket * ********************************/ memset( &sst[s].sin, 0, sizeof(sst[s].sin) ); /* bzero is a unix system call */ sst[s].sin.sin_family = AF_INET; sst[s].sin.sin_addr.s_addr = 0; /* INADDR_ANY is a 32bits zero value */ sst[s].sin.sin_port = htons( SERVICE ); /******************* * bind the socket * *******************/ err = bind( s, (struct sockaddr *)&sst[s].sin, sizeof(sst[s].sin) ); if (err < 0) { Print( "can't bind to port %d, error %d\n\r", SERVICE, err ); closesocket( s ); Nterm(); return err; } Print( "bind to port %d seccessful!\n\r",SERVICE); /****************** * make listening * ******************/ err = listen( s, QLEN ); if (type == SOCK_STREAM && err < 0) { closesocket( s ); Nterm(); return err; } Print( "Now Listening!\n\r"); /********** * select * **********/ FD_ZERO( &rfds ); es = 1; for (i = 0; i < SOCKETS; i++) { sst[i].active = 0; sst[i].init = 0; } sst[s].active = 1; /* master socket is active */ sin_len = sizeof( ssin ); seltime.tv_sec=0; seltime.tv_usec=0; // Main service loop Print( "Now Service loop!\n\r"); while (es) { for (i = 0; i < SOCKETS; i++) { if (sst[i].active) { /* re-join active sockets */ FD_SET( i, &rfds ); } } rc = selectsocket( SOCKETS, &rfds, NULL, NULL, &seltime );//check the socket come in if (rc < 0) { Print( "selectsocket error %d\n\r", rc ); break; } if( !rc )//no socket come in , continue waitting continue; //some sockets come in for (i = 0; i < SOCKETS; i++) { /* scan all possible sockets */ if (FD_ISSET(i, &rfds)) { if (i == s) { /* master socket */ memset( &ssin, 0, sizeof(ssin) ); err = ss = accept( s, (struct sockaddr *)&ssin, &sin_len ); if (err < 0) { Print( "accept error %d\n\r", err ); break; } err=send( ss, Message1, strlen(Message1), 0 );//send connection message to client FD_SET( ss, &rfds );//set the setting sst[ss].active = 1;//active sst[ss].init = 1; memcpy( &sst[ss].sin, &ssin, sin_len ); } else { /* slave socket */ do_echo( i );//The client connection is accept and distribution to socket i //So the user can read the message(may be command string or other) //from the socket i. //remember each clinet connection If it is accept by this server //will cause one socket. So the maximun socket (connection) is 31. //In the other word, This server can be connected by 31 client maximun. //for the detail to read string,please refer to function "do_echo()". } } } } /* service loop */ killsockets();//will end the program Nterm();//close ethernet return err; } void Echo_Result(int skt,char *buf,int clen) { int err; err=send( skt,buf,clen, 0 );//send message to client if(err < 0) { /* write error */ Print( "echo write error %d\n\r", err ); shutdown( skt, 0 ); closesocket( skt ); FD_CLR( skt, &rfds ); sst[skt].active = 0; } } int User_Program(int skt,char *buf,int clen) { // skt => client socket // *buf => Client message // clen => message Length // Add user's control process program here // and delete the below codes. DIODATA DIOData[8]; int slot,dodata; char OutBuf[60]; switch(buf[0]) { case '$'://DI function this command string is not standard,user can define itself. switch(buf[1]) { case 'S':case 's'://slot slot=ascii_to_hex(buf[2]); switch(NameOfModule[slot]) { case 51:case 53://16 bit DI DIOData[slot].data16=DI_16(slot); sprintf(OutBuf,"%04X",DIOData[slot].data16); Echo_Result(skt,OutBuf,strlen(OutBuf));//send message to client break; case 56:case 57://16 bit DO read back sprintf(OutBuf,"%04X",DIOData[slot].data16); Echo_Result(skt,OutBuf,strlen(OutBuf));//send message to client break; case 54:case 55://8bit DI and 8 bit DO read back DIOData[slot].data8.di8=DI_8(slot); sprintf(OutBuf,"%04X",DIOData[slot].data16); Echo_Result(skt,OutBuf,strlen(OutBuf));//send message to client break; default: Echo_Result(skt,ErrorMessage,strlen(ErrorMessage));//send message to client break; } break; default: Echo_Result(skt,ErrorMessage,strlen(ErrorMessage));//send message to client break; } break; case '#'://DO function switch(buf[1]) { case 'S':case 's'://slot slot=ascii_to_hex(buf[2]); switch(NameOfModule[slot]) { case 56:case 57://16 bit DO dodata = (ascii_to_hex(buf[3])<<12)+(ascii_to_hex(buf[4])<<8) +(ascii_to_hex(buf[5])<<4)+ascii_to_hex(buf[6]); DIOData[slot].data16=dodata; DO_16(slot,dodata); Echo_Result(skt,">",1);//send message to client break; case 54:case 55://8bit Do dodata = (ascii_to_hex(buf[3])<<4)+ascii_to_hex(buf[4]); DIOData[slot].data8.do8=dodata; DIO_DO_8(slot,dodata); Echo_Result(skt,">",1);//send message to client break; default: Echo_Result(skt,ErrorMessage,strlen(ErrorMessage));//send message to client break; } break; default: Echo_Result(skt,ErrorMessage,strlen(ErrorMessage));//send message to client break; } break; } return 0; }