예제 #1
0
//! The main function.
int main(int argc, char **argv)
{
  pruIo *io = pruio_new(PRUIO_DEF_ACTIVE, 0x98, 0, 1); //! create new driver structure
  do {
    if (io->Errr) {
               printf("initialisation failed (%s)\n", io->Errr); break;}

    if (pruio_config(io, 1, 0x1FE, 0, 4)) {
                       printf("config failed (%s)\n", io->Errr); break;}

    struct termios oldt, newt; //             make terminal non-blocking
    tcgetattr( STDIN_FILENO, &oldt );
    newt = oldt;
    newt.c_lflag &= ~( ICANON | ECHO );
    newt.c_cc[VMIN] = 0;
    newt.c_cc[VTIME] = 0;
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);

    while(!isleep(1)) { //                      run loop until keystroke
      printf("\r%1X", pruio_gpio_Value(io, PIN));
      fflush(STDIN_FILENO);
    }
    tcsetattr(STDIN_FILENO, TCSANOW, &oldt); //           reset terminal

    printf("\n");
  } while (0);

  pruio_destroy(io);       /* destroy driver structure */
	return 0;
}
예제 #2
0
//! The main function.
int main(int argc, char **argv)
{
  pruIo *Io = pruio_new(PRUIO_DEF_ACTIVE, 0x98, 0, 1); //! ouvrir l'interruption Pruss (/ dev / uio5),charger les instructions de pasm_init.p au PRU et les exécute, et appeler les fonctions initialize des UDT du sous-système.
  do {
    if (Io->Errr) {
               printf("initialisation failed (%s)\n", Io->Errr); break;}

    if (pruio_cap_config(Io, P_IN, 2.)) { //         Cette fonction configure un axe d'en-tête pour la capture et Analyse Pulse (CAP) trains. La configuration des broches est vérifié. Si elle est pas configuré comme entrée pour le module de la Cap dans le sous-système PWM, libpruio essaie d'adapter le muxing broches.
          printf("failed setting input @P_IN (%s)\n", Io->Errr); break;}

    float_t
        f1 //                         Variable for calculated frequency.
      , d1 //                        Variable for calculated duty cycle.
      , f0 = 31250 //                            The required frequency.
      , d0 = .5;   //                           The required duty cycle.
      
    if (pruio_pwm_setValue(Io, P_OUT, f0, d0)) { //Cette fonction définit la sortie PWM sur une broche d'en-tête. sortie PWM peuvent être soit générés par un eHRPWM ou d'un module eCAP. En fonction du nombre de broches spécifié (paramètre à billes), le module PWM correspondant est configuré pour la fréquence et le rapport cyclique déterminé.
        printf("failed setting output @P_OUT (%s)\n", Io->Errr); break;}


    if (pruio_config(Io, 1, 0x1FE, 0, 4)) { //Cette fonction est utilisée pour télécharger la configuration de l'hôte (ARM) au conducteur (PRU). Le PRU s'arrêté (si en cours d'exécution) et les nouvelles configurations se charger. Aussi les instructions Pru_Run se ré-initialisés.
                       printf("config failed (%s)\n", Io->Errr); break;}

    struct termios oldt, newt; //             make terminal non-blocking
    tcgetattr( STDIN_FILENO, &oldt );
    newt = oldt;
    newt.c_lflag &= ~( ICANON );
    newt.c_cc[VMIN] = 0;
    newt.c_cc[VTIME] = 1;
    tcsetattr( STDIN_FILENO, TCSANOW, &newt );

    while(1) { //                                       run endless loop
      if (1 == isleep(1)) {
        
        if (pruio_pwm_setValue(Io, P_OUT, f0, d0)) { //   set new output
           printf("failed setting PWM output (%s)\n", Io->Errr); break;}

        printf("\n--> Frequency: %10f , Duty: %10f\n", f0, d0); //  info
      }

      if (pruio_cap_Value(Io, P_IN, &f1, &d1)) { //    get current input
          printf("failed reading input @P_IN (%s)\n", Io->Errr); break;}

      printf("\r    Frequency: %10f , Duty: %10f     ", f1, d1); // info
      fflush(STDIN_FILENO);
    }

finish:
    tcsetattr( STDIN_FILENO, TCSANOW, &oldt ); //         reset terminal

    printf("\n");
  } while (0);

  pruio_destroy(Io);       /* destroy driver structure */
	return 0;
}
예제 #3
0
/********************************************************************************
 * TvCtrlPointTimerLoop
 *
 * Description: 
 *       Function that runs in its own thread and monitors advertisement
 *       and subscription timeouts for devices in the global device list.
 *
 * Parameters:
 *    None
 *
 ********************************************************************************/
void *
TvCtrlPointTimerLoop( void *args )
{
    int incr = 30;              // how often to verify the timeouts, in seconds

    while( 1 ) {
        isleep( incr );
        TvCtrlPointVerifyTimeouts( incr );
    }
}
예제 #4
0
파일: tv_ctrlpt.c 프로젝트: Tieske/pupnp
void *TvCtrlPointTimerLoop(void *args)
{
	/* how often to verify the timeouts, in seconds */
	int incr = 30;

	while (TvCtrlPointTimerLoopRun) {
		isleep((unsigned int)incr);
		TvCtrlPointVerifyTimeouts(incr);
	}

	return NULL;
	args = args;
}
예제 #5
0
int main()
{
	client_sock = make_sock("127.0.0.1");
	ikcpcb *kcp = ikcp_create(0x11223344, (void*)0);
	kcp->output = udp_output;
	ikcp_wndsize(kcp, 128, 128);
	ikcp_nodelay(kcp, 0, 10, 0, 0);

	char buf[ECHO_LEN];
	char *buf_in;
	char *msg = "hello";
	int i=0;
	int current;
	int ret;
	for(;;)
	{
		++i;
		isleep(1);
		current = iclock();
		ikcp_update(kcp, current);

		if (i % 1000 == 0)
		{
			sprintf(buf, "%s:%d, %u", msg, i, current);
			ret = ikcp_send(kcp, buf, strlen(buf));
			check(ret >= 0, "send");
			printf("send [%s]\n", buf);
		}

		ret = recv(client_sock, buf, ECHO_LEN-1, 0);
		check_silently(ret > 0);

		ikcp_input(kcp, buf, ret);
		printf("\nrecv from server raw: %s\n", buf);

		ret = ikcp_recv(kcp, buf, ECHO_LEN-1);
		check_silently(ret > 0);

		buf[ret] = '\0';
		printf("\nrecv from server: %s\n", buf);

error:
		continue;
	}
}
예제 #6
0
파일: miniserver.c 프로젝트: hotgloupi/upnp
int StopMiniServer()
{
	char errorBuffer[ERROR_BUFFER_LEN];
	socklen_t socklen = sizeof (struct sockaddr_in);
	SOCKET sock;
	struct sockaddr_in ssdpAddr;
	char buf[256] = "ShutDown";
	size_t bufLen = strlen(buf);

	switch(gMServState) {
	case MSERV_RUNNING:
		gMServState = MSERV_STOPPING;
		break;
	default:
		return 0;
	}
	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock == INVALID_SOCKET) {
		strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
		UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
			"SSDP_SERVER: StopSSDPServer: Error in socket() %s\n",
			errorBuffer);
		return 0;
	}
	while(gMServState != (MiniServerState)MSERV_IDLE) {
		ssdpAddr.sin_family = (sa_family_t)AF_INET;
		ssdpAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
		ssdpAddr.sin_port = htons(miniStopSockPort);
		sendto(sock, buf, bufLen, 0,
			(struct sockaddr *)&ssdpAddr, socklen);
		usleep(1000u);
		if (gMServState == (MiniServerState)MSERV_IDLE) {
			break;
		}
		isleep(1u);
	}
	sock_close(sock);

	return 0;
}
예제 #7
0
/************************************************************************
 * Function: StopMiniServer
 *
 * Parameters:
 *	void
 *
 * Description:
 * 	Stop and Shutdown the MiniServer and free socket 
 *	resources.
 *
 * Return: int
 *		Always returns 0 
 ************************************************************************/
int
StopMiniServer( void )
{

    int socklen = sizeof( struct sockaddr_in );
    int sock;
    struct sockaddr_in ssdpAddr;
    char buf[256] = "ShutDown";
    int bufLen = strlen( buf );

    if( gMServState == MSERV_RUNNING ) {
        gMServState = MSERV_STOPPING;
    } else {
        return 0;
    }

    sock = socket( AF_INET, SOCK_DGRAM, 0 );
    if( sock == DLNA_INVALID_SOCKET ) {
        dlnaPrintf( DLNA_INFO, SSDP, __FILE__, __LINE__,
            "SSDP_SERVER:StopSSDPServer: Error in socket operation !!!\n" );
        return 0;
    }

    while( gMServState != MSERV_IDLE ) {
        ssdpAddr.sin_family = AF_INET;
        ssdpAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
        ssdpAddr.sin_port = htons( miniStopSockPort );
        sendto( sock, buf, bufLen, 0, ( struct sockaddr * )&ssdpAddr,
                socklen );
        usleep( 1000 );
        if( gMServState == MSERV_IDLE )
            break;
        isleep( 1 );
    }
    shutdown( sock, SD_BOTH );
    dlnaCloseSocket( sock );
    return 0;
}
예제 #8
0
/************************************************************************
 * Function: RunMiniServer
 *
 * Parameters:
 *	MiniServerSockArray *miniSock - Socket Array
 *
 * Description:
 * 	Function runs the miniserver. The MiniServer accepts a 
 *	new request and schedules a thread to handle the new request.
 *	Checks for socket state and invokes appropriate read and shutdown 
 *	actions for the Miniserver and SSDP sockets 
 *
 * Return: void
 ************************************************************************/
static void
RunMiniServer( MiniServerSockArray * miniSock )
{
    struct sockaddr_in clientAddr;
    socklen_t clientLen;
    SOCKET connectHnd;
    SOCKET miniServSock = miniSock->miniServerSock;
    SOCKET miniServStopSock =  miniSock->miniServerStopSock;
    SOCKET ssdpSock = miniSock->ssdpSock;
#ifdef INCLUDE_CLIENT_APIS
    SOCKET ssdpReqSock = miniSock->ssdpReqSock;
#endif

    fd_set expSet;
    fd_set rdSet;
    int maxMiniSock;
    int byteReceived;
    char requestBuf[256];

    maxMiniSock = max( miniServSock, miniServStopSock) ;
    maxMiniSock = max( maxMiniSock, (SOCKET)(ssdpSock) );
#ifdef INCLUDE_CLIENT_APIS
    maxMiniSock = max( maxMiniSock, (SOCKET)(ssdpReqSock) );
#endif
    ++maxMiniSock;

    gMServState = MSERV_RUNNING;
    while( TRUE ) {
        FD_ZERO( &rdSet );
        FD_ZERO( &expSet );

        FD_SET( miniServStopSock, &expSet );
        FD_SET( miniServSock, &rdSet );
        FD_SET( miniServStopSock, &rdSet );
        FD_SET( ssdpSock, &rdSet );
#ifdef INCLUDE_CLIENT_APIS
        FD_SET( ssdpReqSock, &rdSet );
#endif

        if( select( maxMiniSock, &rdSet, NULL, &expSet, NULL ) ==
            DLNA_SOCKETERROR ) {
            dlnaPrintf( DLNA_CRITICAL, SSDP, __FILE__, __LINE__,
                "Error in select call!\n" );
	    /* Avoid 100% CPU in case of repeated error in select() */
	    isleep( 1 );
            continue;
        } else {
            if( FD_ISSET( miniServSock, &rdSet ) ) {
                clientLen = sizeof( struct sockaddr_in );
                connectHnd = accept( miniServSock,
                    ( struct sockaddr * )&clientAddr, &clientLen );
                if( connectHnd == DLNA_INVALID_SOCKET ) {
                    dlnaPrintf( DLNA_INFO, MSERV, __FILE__, __LINE__,
                        "miniserver: Error in accepting connection\n" );
                    continue;
                }
                schedule_request_job( connectHnd, &clientAddr );
            }
#ifdef INCLUDE_CLIENT_APIS
            // ssdp
            if( FD_ISSET( ssdpReqSock, &rdSet ) ) {
                readFromSSDPSocket( ssdpReqSock );
            }
#endif
            if( FD_ISSET( ssdpSock, &rdSet ) ) {
                    readFromSSDPSocket( ssdpSock );
            }
            if( FD_ISSET( miniServStopSock, &rdSet ) ) {
                clientLen = sizeof( struct sockaddr_in );
                memset( ( char * )&clientAddr, 0,
                        sizeof( struct sockaddr_in ) );
                byteReceived =
                    recvfrom( miniServStopSock, requestBuf, 25, 0,
                              ( struct sockaddr * )&clientAddr,
                              &clientLen );
                if( byteReceived > 0 ) {
                    requestBuf[byteReceived] = '\0';
                    dlnaPrintf( DLNA_INFO, MSERV, __FILE__, __LINE__,
                        "Received response !!!  %s From host %s \n",
                        requestBuf, inet_ntoa( clientAddr.sin_addr ) );
                    dlnaPrintf( DLNA_PACKET, MSERV, __FILE__, __LINE__,
                        "Received multicast packet: \n %s\n",
                        requestBuf );
                    if( NULL != strstr( requestBuf, "ShutDown" ) ) {
                        break;
		    }
                }
            }
        }
    }

    shutdown( miniServSock, SD_BOTH );
    dlnaCloseSocket( miniServSock );
    shutdown( miniServStopSock, SD_BOTH );
    dlnaCloseSocket( miniServStopSock );
    shutdown( ssdpSock, SD_BOTH );
    dlnaCloseSocket( ssdpSock );
#ifdef INCLUDE_CLIENT_APIS
    shutdown( ssdpReqSock, SD_BOTH );
    dlnaCloseSocket( ssdpReqSock );
#endif

    free( miniSock );
    gMServState = MSERV_IDLE;

    return;
}
예제 #9
0
파일: adc_test.c 프로젝트: mvf4z7/rosa
//! The main function.
int main(int argc, char **argv)
{
  pruIo *Io = pruio_new(PRUIO_DEF_ACTIVE, 0x98, 0, 1); //! create new driver structure
  do {
    if (Io->Errr) {
               printf("initialisation failed (%s)\n", Io->Errr); break;}

    if (pruio_cap_config(Io, P_IN, 2.)) { //         configure input pin
          printf("failed setting input @P_IN (%s)\n", Io->Errr); break;}

    float_t
        f1 //                         Variable for calculated frequency.
      , d1 //                        Variable for calculated duty cycle.
      , f0 = .5 //                            The required frequency.
      , d0 = .5;   //                           The required duty cycle.
    if (pruio_pwm_setValue(Io, P_OUT, f0, d0)) {
        printf("failed setting output @P_OUT (%s)\n", Io->Errr); break;}

    //           pin config OK, transfer local settings to PRU and start
    if (pruio_config(Io, 1, 0x1FE, 0, 4)) {
                       printf("config failed (%s)\n", Io->Errr); break;}

    struct termios oldt, newt; //             make terminal non-blocking
    tcgetattr( STDIN_FILENO, &oldt );
    newt = oldt;
    newt.c_lflag &= ~( ICANON );
    newt.c_cc[VMIN] = 0;
    newt.c_cc[VTIME] = 1;
    tcsetattr( STDIN_FILENO, TCSANOW, &newt );

    while(1) { //                                       run endless loop
      if (1 == isleep(1)) {
        switch (getchar()) { //                       evaluate keystroke
          case '0' : d0 = 0.0; break;
          case '1' : d0 = 0.1; break;
          case '2' : d0 = 0.2; break;
          case '3' : d0 = 0.3; break;
          case '4' : d0 = 0.4; break;
          case '5' : d0 = 0.5; break;
          case '6' : d0 = 0.6; break;
          case '7' : d0 = 0.7; break;
          case '8' : d0 = 0.8; break;
          case '9' : d0 = 0.9; break;
          case ',' : d0 = 1.0; break;
          case 'm' : f0 = (f0 > 5.5 ? f0 - 5. : .5); break;
          case 'p' : f0 = (f0 < 999995. ? f0 + 5. : 1000000.); break;
          case '*' : f0 = (f0 < 1000000 ? f0 * 2 : 1000000.); break;
          case '/' : f0 = (f0 > .5 ? f0 / 2 : .5); break;
          case '+' : f0 = 1000000; break;
          case '-' : f0 = .5; break;
          default: goto finish;
        };
        if (pruio_pwm_setValue(Io, P_OUT, f0, d0)) { //   set new output
           printf("failed setting PWM output (%s)\n", Io->Errr); break;}

        printf("\n--> Frequency: %10f , Duty: %10f\n", f0, d0); //  info
      }

      if (pruio_cap_Value(Io, P_IN, &f1, &d1)) { //    get current input
          printf("failed reading input @P_IN (%s)\n", Io->Errr); break;}

      printf("\r    Frequency: %10f , Duty: %10f     ", f1, d1); // info
      fflush(STDIN_FILENO);
    }

finish:
    tcsetattr( STDIN_FILENO, TCSANOW, &oldt ); //         reset terminal

    printf("\n");
  } while (0);

  pruio_destroy(Io);       /* destroy driver structure */
	return 0;
}
예제 #10
0
//-------------------------------! The main function.
int main(int argc, char **argv)
{   float_t f1 = 500.0F; 			//      Variable for calculated frequency.
    float_t d1 = 0.9F; 				//      Variable for calculated duty cycle.
    float_t f0 = 500.0F;   			//      The required frequency.
    float_t d0 = .9F;    			//      The required duty cycle.
    float_t MINFREQ = 2.0F;         //
    char buffer[256], *msg = buffer;
    pruIo *Io;
    int charX=0;

    Io = pruio_new(PRUIO_DEF_ACTIVE, 16, 0x98, 0); 		//pruIo* pruio_new(uint16 Act, uint8 Av, uint32 OpD, uint8 SaD);
    pruio_destroy(Io);       							//destroy driver structure
    Io = pruio_new(PRUIO_DEF_ACTIVE, 16, 0x98, 0); 		//pruIo* pruio_new(uint16 Act, uint8 Av, uint32 OpD, uint8 SaD);

    //output GpioUdt::setValue PwmMod::setValue
    //input  GpioUdt::config   CapMod::config

    msg= pruio_pwm_setValue(Io, P_FANA, f0, d0);
    if(msg)printf("1%s\n",msg);	//char* pruio_pwm_setValue(pruIo* Io, uint8 Ball, float_t Hz, float_t Du);
    msg= pruio_pwm_setValue(Io, P_FANB, f0, d0);
    if(msg)printf("2%s\n",msg);	//char* pruio_pwm_setValue(pruIo* Io, uint8 Ball, float_t Hz, float_t Du);
    msg= pruio_config(Io, 1, 0x1FE, 1e6, 0);
    if(msg)printf("3%s\n",msg);	//char* pruio_config(pruIo* Io, uint32 Samp, uint32 Mask, uint32 Tmr, uint16 Mds);
    msg= pruio_cap_config(Io, (uint8)P_IN, MINFREQ);			//NO NON-FLOAT with decimal, get interpreted at double
    if(msg)printf("4%s\n",msg);	//char* pruio_cap_config(pruIo* Io, uint8 Ball, float_t FLow);


// not using ring buffer mode. couldn't get 2 PWM outputs to work with SAMP>1
// So TMR value is ignored
//	msg= pruio_rb_start(Io);						if(msg)printf("5%s\n",msg);	//char* pruio_rb_start(pruIo* Io);

	printf("Samples: %d\n",    Io->Adc->Samples);
	printf("TimerVal: %d ns\n",Io->Adc->TimerVal);
//	printf("Dram[0]= %d\n",Io->DRam[0] );			//most recent write position

    struct termios oldt, newt; //             make terminal non-blocking
    int localerr=0;
    if( 0>tcgetattr( STDIN_FILENO, &oldt ) )
   	{	localerr = errno;
    	printf("tcgetattr failed, error = %d\n",localerr);
   	}
    newt = oldt;
    newt.c_lflag &= ~( ICANON );
    newt.c_cc[VMIN] = 0;
    newt.c_cc[VTIME] = 1;
    tcsetattr( STDIN_FILENO, TCSANOW, &newt );

    int irun=1;
    while(irun)								// Terminate on ESC, else run endless loop
    {	if (1 == isleep(1000)) 				// got a char
    	{	charX = getchar();
    		switch (charX)					// evaluate keystroke
			{ 	case '0' : d0 = 0.0; break;
				case '1' : d0 = 0.1; break;
				case '2' : d0 = 0.2; break;
				case '3' : d0 = 0.3; break;
				case '4' : d0 = 0.4; break;
				case '5' : d0 = 0.5; break;
				case '6' : d0 = 0.6; break;
				case '7' : d0 = 0.7; break;
				case '8' : d0 = 0.8; break;
				case '9' : d0 = 0.9; break;
				case ',' : d0 = 1.0; break;
				case 'm' : f0 = (f0 > 5.5 ? f0 - 5. : .5); break;
				case 'p' : f0 = (f0 < 999995. ? f0 + 5. : 1000000.); break;
				case '*' : f0 = (f0 < 1000000 ? f0 * 2 : 1000000.); break;
				case '/' : f0 = (f0 > .5 ? f0 / 2 : .5); break;
				case '+' : f0 = 1000000; break;
				case '-' : f0 = .5; break;
				default: {irun = 0; break;}				//anything other than above, quit
			};

    		if(irun)
    		{	msg = pruio_pwm_setValue(Io, P_FANA, f0, d0);
				if(msg)
				{	printf("6failed setting PWMA output (%s)\n", Io->Errr); irun=0;
				}else
				{	printf("6\n");
				}
				msg = pruio_pwm_setValue(Io, P_FANB, f0, d0);
				if(msg)
				{	printf("7failed setting PWMB output (%s)\n", Io->Errr); irun=0;
				}else
				{	printf("7\n");
				}
    		}
    	}

    	if(irun)
    	{	  if (pruio_cap_Value(Io, P_IN, &f1, &d1)) 		//    get current input
			  {		printf("8failed reading input @P_IN=%d (%s)\n", P_IN, Io->Errr); break;
			  }
			   printf("Freq %6.1f Duty: %6.1f Freq: %6.1f Duty: %6.1f ADC: %4d %4d %4d\n", f0, d0, f1, d1,Io->Adc->Value[1],Io->Adc->Value[2],Io->Adc->Value[3]); // info
			  fflush(STDIN_FILENO);
    	}
    } //end while


    tcsetattr( STDIN_FILENO, TCSANOW, &oldt ); 		//         reset terminal
    printf("Exiting\n");

    if (pruio_pwm_setValue(Io, P_FANA, f0, 1))	   //   set new output
	{   printf("failed setting PWMA output (%s)\n", Io->Errr);
	}
    if (pruio_pwm_setValue(Io, P_FANB, f0, 1))	   //   set new output
	{   printf("failed setting PWMB output (%s)\n", Io->Errr);
	}

    pruio_destroy(Io);       					//destroy driver structure
	return 0;
}
예제 #11
0
파일: test.cpp 프로젝트: Mephostopilis/lua
// 测试用例
void test(int mode)
{
	// 创建模拟网络:丢包率10%,Rtt 60ms~125ms
	vnet = new LatencySimulator(10, 60, 125);

	// 创建两个端点的 kcp对象,第一个参数 conv是会话编号,同一个会话需要相同
	// 最后一个是 user参数,用来传递标识
	ikcpcb *kcp1 = ikcp_create(0x11223344, (void*)0);
	ikcpcb *kcp2 = ikcp_create(0x11223344, (void*)1);

	// 设置kcp的下层输出,这里为 udp_output,模拟udp网络输出函数
	kcp1->output = udp_output;
	kcp2->output = udp_output;

	IUINT32 current = iclock();
	IUINT32 slap = current + 20;
	IUINT32 index = 0;
	IUINT32 next = 0;
	IINT64 sumrtt = 0;
	int count = 0;
	int maxrtt = 0;

	// 配置窗口大小:平均延迟200ms,每20ms发送一个包,
	// 而考虑到丢包重发,设置最大收发窗口为128
	ikcp_wndsize(kcp1, 128, 128);
	ikcp_wndsize(kcp2, 128, 128);

	// 判断测试用例的模式
	if (mode == 0) {
		// 默认模式
		ikcp_nodelay(kcp1, 0, 10, 0, 0);
		ikcp_nodelay(kcp2, 0, 10, 0, 0);
	}
	else if (mode == 1) {
		// 普通模式,关闭流控等
		ikcp_nodelay(kcp1, 0, 10, 0, 1);
		ikcp_nodelay(kcp2, 0, 10, 0, 1);
	}	else {
		// 启动快速模式
		// 第二个参数 nodelay-启用以后若干常规加速将启动
		// 第三个参数 interval为内部处理时钟,默认设置为 10ms
		// 第四个参数 resend为快速重传指标,设置为2
		// 第五个参数 为是否禁用常规流控,这里禁止
		ikcp_nodelay(kcp1, 1, 10, 2, 1);
		ikcp_nodelay(kcp2, 1, 10, 2, 1);
		kcp1->rx_minrto = 10;
		kcp1->fastresend = 1;
	}


	char buffer[2000];
	int hr;

	IUINT32 ts1 = iclock();

	while (1) {
		isleep(1);
		current = iclock();
		ikcp_update(kcp1, iclock());
		ikcp_update(kcp2, iclock());

		// 每隔 20ms,kcp1发送数据
		for (; current >= slap; slap += 20) {
			((IUINT32*)buffer)[0] = index++;
			((IUINT32*)buffer)[1] = current;

			// 发送上层协议包
			ikcp_send(kcp1, buffer, 8);
		}

		// 处理虚拟网络:检测是否有udp包从p1->p2
		while (1) {
			hr = vnet->recv(1, buffer, 2000);
			if (hr < 0) break;
			// 如果 p2收到udp,则作为下层协议输入到kcp2
			ikcp_input(kcp2, buffer, hr);
		}

		// 处理虚拟网络:检测是否有udp包从p2->p1
		while (1) {
			hr = vnet->recv(0, buffer, 2000);
			if (hr < 0) break;
			// 如果 p1收到udp,则作为下层协议输入到kcp1
			ikcp_input(kcp1, buffer, hr);
		}

		// kcp2接收到任何包都返回回去
		while (1) {
			hr = ikcp_recv(kcp2, buffer, 10);
			// 没有收到包就退出
			if (hr < 0) break;
			// 如果收到包就回射
			ikcp_send(kcp2, buffer, hr);
		}

		// kcp1收到kcp2的回射数据
		while (1) {
			hr = ikcp_recv(kcp1, buffer, 10);
			// 没有收到包就退出
			if (hr < 0) break;
			IUINT32 sn = *(IUINT32*)(buffer + 0);
			IUINT32 ts = *(IUINT32*)(buffer + 4);
			IUINT32 rtt = current - ts;
			
			if (sn != next) {
				// 如果收到的包不连续
				printf("ERROR sn %d<->%d\n", (int)count, (int)next);
				return;
			}

			next++;
			sumrtt += rtt;
			count++;
			if (rtt > (IUINT32)maxrtt) maxrtt = rtt;

			printf("[RECV] mode=%d sn=%d rtt=%d\n", mode, (int)sn, (int)rtt);
		}
		if (next > 1000) break;
	}

	ts1 = iclock() - ts1;

	ikcp_release(kcp1);
	ikcp_release(kcp2);

	const char *names[3] = { "default", "normal", "fast" };
	printf("%s mode result (%dms):\n", names[mode], (int)ts1);
	printf("avgrtt=%d maxrtt=%d tx=%d\n", (int)(sumrtt / count), (int)maxrtt, (int)vnet->tx1);
	printf("press enter to next ...\n");
	char ch; scanf("%c", &ch);
}