/* XDemo65: Time Synchronization using ICMP protocol Compiler: BC++ 3.1 Compile mode: large Project: icmp.c user.c Vsocket.c v7000.c vModbus.c [after vcom3002.lib] ..\Lib\7188EL.Lib ..\Lib\TCPIP32.Lib ..\Lib\VcomNNNN.Lib, with NNNN being the lib file's version. The demo is used to synchronize the time of a computer client or server to another server or reference time source through ICMP protocol, Type13,14 (Timestamp Request and Timestamp Reply Message) The timestamp values are in milliseconds from midnight UT (Greenwich mean time) Orig Recv Xmit RecvReply |----------------------->| |------------------------->| |<----------------------- RTT -------------------------->| RTT(round-trip time),Recv=Xmit diff=RTT/2-(Recv-Orig)=(RecvReply-Orig)/2-(RecvReply-Xmit) diff (It's the time difference between the 7188E and Time server) 19s -->Send a command to start a connection for time synchronization The client functions consist of the icmp_open(),icmp_close(),icmp_write() and icmp_read() in "Vsocket.C". Hardware: 7188E modules * 1 (client) Time server: time-a.nist.gov 129.6.15.28 time-b.nist.gov 129.6.15.29 Refer 7188e\TCP\Doc\[Big5|Eng|Gb2312]\Vxcomm.htm 7188e\TCP\Xserver\Xserver.htm 7188e\TCP\Xserver\Function.htm to get more information. Because the kernal of Xserver used InstallCom() function. Please use printCom1() instead of Print() if you want to send formatted output from COM1. [28/Mar/2003] by Sean [06,Oct,2004] Commented by Annita [11/Aug/2005] by Liam [26,July,2011] by Nicholas */ #include #include #include #include "..\lib\7188e.h" #include "..\lib\tcpip32.h" #include "..\lib\vxcomm.h" #define TaiwanTime 8 //GMT+ 8.00 struct IcmpTime { unsigned short Identifier; unsigned short SequenceNumber; unsigned long OriTimeStamp; unsigned long ReceiveTimeStamp; unsigned long TransmitTimeStamp; }; int iOutskt; //the socket number of connecting unsigned char iIpStr[17]; //the IP of the server int Recesucceed=0; extern jmp_buf jumper; unsigned long stime; int iStart,iSocket; extern struct IcmpTime *timestamp; void UserCount(void) { /* User's timer trigger function. Please refer to XDemo04 for detail description. Please refer to XDemo09 for example code. */ } void UserInit(void) { /* Initialize user's program. Please refer to XDemo04 for detail description. Please refer to XDemo09 for example code. */ SetBaudrate1(115200L); iStart=0; sprintf(iIpStr,"129.6.15.28"); //change the ip to fit your time server. } void UserLoopFun(void) { /* VxComm.exe will call this function every scan time Please refer to XDemo11 for Real-time I/O control */ int iRet,i; extern int errno; char sCommand[200]; unsigned long lfinishtime; unsigned int hour,minu,sec; unsigned long temp; if(iStart==1) { iOutskt=icmp_open(iIpStr); //buildsockets iStart=0; printCom1("Socket number:%d!!\r\n\r\n",iOutskt); if (iOutskt<0){ printCom1("connect error!!\r\n"); iSocket=0; longjmp(jumper,1); } else iSocket=1; } if(iSocket==1) { if(Recesucceed==0) { iRet=icmp_write(iOutskt); if (iRet<0)// write error { printCom1("echo Send error,code(%d)\r\n",iRet); icmp_close(iOutskt); iSocket=0; goto End; } else stime=*TimeTicks; } iRet=icmp_read(iOutskt,700L,&lfinishtime); if (iRet<=0)// read error { if(iRet==ETIMEDOUT) //Detect whether the error of recv is timeout. { if(*TimeTicks-stime<10000) //10 sec { Recesucceed=1; printCom1("echo Receive timeout \r\n"); } else { Recesucceed=0; iSocket=0; printCom1("Receive timeout over 10 sec\r\n",iRet); icmp_close(iOutskt); } } else { Recesucceed=0; iSocket=0; printCom1("echo Receive error,code(%d)\r\n",iRet); icmp_close(iOutskt); } } else { temp=(htonl(timestamp->ReceiveTimeStamp)+1)+(lfinishtime-timestamp->OriTimeStamp)/2; //diff+lfinishtime+1 (1ms means process time) hour=(temp/1000)/3600; //60*60 minu=((temp/1000)-hour*60*60)/60; //60 sec=(temp/1000)-hour*60*60-minu*60; SetTime((hour+TaiwanTime)%24,minu,sec); Delay(10); sprintf(sCommand,"New hour:%d ,minu:%d ,sec:%d\r\n",(hour+TaiwanTime)%24,minu,sec); printCom1(sCommand); Recesucceed=0; iSocket=0; icmp_close(iOutskt); } } End: } int UserCmd(unsigned char *Cmd,unsigned char *Response) { /* Xserver executes this function when received a package form TCP port 10000 and the first two bytes are "19". Funtion of Xserver, Please refer to XDemo04 for detail description. */ strlwr(Cmd); if(Cmd[0]='s') iStart=1; return 1; /* return error */ } int VcomUserBinaryCmd(TCPREADDATA *p) { /* VXCOMM.EXE 2.6.12(04,Sep,2001) or later will support this function. Xserver executes this function when received a package form TCP port 10000 and the first two bytes are "23". Please refer to XDemo04 for detail description. Please refer to XDemo23 for example code. */ return 1; /* any value will be accept */ } int VcomCmdUser(TCPREADDATA *p) { /* VCOM3005 (Feb,22,2002) or later will call this function for PortUser. When packets received by TCP PORT PortUser(user defined) of 7188E/8000E, Xserver will call this function. Please refer to XDemo04 for detail description. */ VcomSendSocket(p->Socket,p->ReadUartChar,p->Length); return 1; /* any value will be accept */ } void PortUserStart(int skt) { /* XS8_3200.Lib Version 3.2.00 (20,Apr,2004) or later version supports this function. When a TCP/IP client connects to the 7188E/8000E via the user's defined port(PortUser), the Xserver calls the function once. Please refer to XDemo04 for detail description. */ skt=skt; //do nothing } void Port9999Start(int skt) { /* XS8_3200.Lib Version 3.2.00 (20,Apr,2004) or later version supports this function. When a TCP/IP client connects to the 7188E/8000E TCP port 9999, the Xserver calls the function once. Please refer to XDemo04 for detail description. */ skt=skt; //do nothing } void Port502Start(int skt) { /* XS8_3200.Lib Version 3.2.00 (20,Apr,2004) or later version supports this function. When a TCP/IP client connects to the 7188E/8000E TCP port 502, the Xserver calls the function once. Please refer to XDemo04 for detail description. */ skt=skt; //do nothing }