openwrt中开发ser2tcpclient(串口转tcp实现高速透传)

概要

开源项目ser2net作为Linux/openwrt系统下串口转以太网服务端使用非常广泛, 并且非常适合作为被动监听连接场景下的物联网设备使用,本文开发的ser2tcpclient就是将串口转为tcp协议为主的客户端,方便在局域网中实现高速的点对点通信。

整体架构流程

1.soc串口采用mavlink的状态机协议不断的接收mcu上报的数据帧。

2.无线网络管理器不断尝试搜索,连接,认证,握手,通信数据加解密,通信虚拟时间同步,双向数据透传和监听无线信号。

3.程序本身异常情况监听和处理。

技术细节

使用mavlink协议状态机接收mcu上报的数据帧

	 while(TRUE){

	  readbuflen = serial_recv(gd_serial_fd,readbuf,RECV_BUFFER_SIZE);
	  if(readbuflen <= 0){
		  continue;
	  }
	  
      //解析出完整的数据包
	  #if 0
	  printf("retval=%d\n",readbuflen);
	  print0x(readbuf,readbuflen);
      #endif
	 

	  databuf				  = readbuf;
	  is_parse_complete	      = 0;

	  
	  while(readbuflen--)
	  {
		   //if(Mavlink_Frame_Char_Buffer(&rxmsg_dev,&status_dev,*databuf++,FALSE)
		   if(Mavlink_Frame_Char_Buffer(&rxmsg_dev,&status_dev,*databuf++,TRUE)
				 == MAVLINK_FRAMING_OK)
				//!= MAVLINK_FRAMING_INCOMPLETE)
		   {
				is_parse_complete = 1;
		   }
	  }
	  
	  if(!is_parse_complete) continue;

      #if 0
	  printf("recv on frame\n");
      #endif

	  handle_mainboard_read(&rxmsg_dev);
	  
	 }

无线信号的配对,连接,认证,状态监听的管理


/**
有效wifi的连接和tcp server的连接
*/
void* wifi_connect_manager_thread(void*param)
{
     #define WIFI_CONNECT_TIMOUT         (15)
	 #define IWINFO_NC_MAX_CNT           (10)


	 UI8 trycnt;
     I8  data[MAX_BUFFER_CACHE_SIZE];
     I8*cur_board_connect_ssid;
	 
	 BOOLEAN is_cur_board_connect_ssid;
	 I8*cur_board_connect_passwd;
	 BOOLEAN is_cur_board_connect_passwd;

     I8*wlan0ip;
     I8*iwinfoname;
	 I8*iwinfomac;

     UI8 iwinfo_nc_cnt        = 0;
	 UI8 is_iwinfo_need_check = 0; 
	 int tmp_read_cnt         = 0;


     while(TRUE)
	 {
		 if(!strlen(curssid) || is_iwinfo_need_check){

             if(is_iwinfo_need_check) is_iwinfo_need_check = 0;

             iwinfoname = cmd_system(IWINFO_GET_NAME);           
             if(iwinfoname != NULL && 
				strlen(iwinfoname) > 0 && 
				strncmp(IWINFO_GET_NAME_UNKNOWN,iwinfoname,strlen(IWINFO_GET_NAME_UNKNOWN)))
			 {		
				 //bakup cur name
				 memset(data,0,sizeof(data));
				 //需要去除两个双引号加一个换行
				 strncpy(data,iwinfoname + 1,strlen(iwinfoname) - 3 );

				 iwinfomac = cmd_system(IWINFO_GET_MAC);

                 if(iwinfomac != NULL && 
				    strlen(iwinfomac) > 0 && 
				    !strncmp(iwinfomac,DEVICE_FIX_MAC,10))
				 {
  					 #ifdef DEBUG
					 printf("iwinfo get name & mac ok...\n");
					 #endif

					 memset(curssid,'\0',sizeof(curssid));
					 strcpy(curssid,data);
					 memset(curpasswd,'\0',sizeof(curpasswd));
					 strcpy(curpasswd,WPS_MODE_FIX_PASSWD);	
					 
					 continue;
				 }
				 else{
					 #ifdef DEBUG
					 printf("iwinfo get mac is invalid...\n");
					 #endif
				 }
			 }else{

				 #ifdef DEBUG
				 printf("iwinfo get name is invalid...\n");
				 #endif
			 }


			 #ifdef DEBUG
			 printf("curssid is invalid...\n");
			 #endif

			 usleep(DELAY_1S);
			 continue;
		 }

 
         #ifdef DEBUG
         printf("start to connect wifi=%s:%s\n",curssid,curpasswd);
		 #endif


         //避免重复连接已经连上的WiFi
         is_cur_board_connect_ssid   = FALSE;
         cur_board_connect_ssid      = cmd_system(UCI_GET_SSID);
		 //忽略结尾0x0A
		 if(!strncmp(curssid,cur_board_connect_ssid,strlen(cur_board_connect_ssid) - 1)) is_cur_board_connect_ssid = TRUE;

		 is_cur_board_connect_passwd = FALSE;
		 cur_board_connect_passwd    = cmd_system(UCI_GET_PASSWD);
		 //忽略结尾0x0A
		 if(!strncmp(curpasswd,cur_board_connect_passwd,strlen(cur_board_connect_passwd) - 1)) is_cur_board_connect_passwd = TRUE;

         if(!(is_cur_board_connect_ssid && 
		 	is_cur_board_connect_passwd 
			)){

			 #ifdef DEBUG
			 printf("wifi_connect do...\n");
			 #endif

			 wifi_connect(curssid,curpasswd);
		     //当切换WiFi时,当前连接的WiFi对wlan0的状态有影响
		     //故延时消除
             //usleep(DELAY_3S);
			 usleep(DELAY_2S);

			 #ifdef DEBUG
			 printf("wifi_connect do complete...\n");
			 #endif

	         trycnt               = 0;
			 while(!wlan0_status() && trycnt++ < WIFI_CONNECT_TIMOUT){
				 #ifdef DEBUG
				 printf("wifi connect failed!\n");
				 #endif
				 usleep(DELAY_100MS);
			 }

			 if(trycnt >= WIFI_CONNECT_TIMOUT){

				 //当一直连接失败时,iwinfo也要周期性检查 
				 if(iwinfo_nc_cnt++ >= IWINFO_NC_MAX_CNT / 2){
					 iwinfo_nc_cnt        = 0;
					 is_iwinfo_need_check = 1; 
				 }

				 continue;
			 }else{
                 iwinfo_nc_cnt            = 0;
			 }
		 }



		 /**
		   WiFi配置已经都对得上,但无线网络接口还未连接上,
		   此种情况等待系统去重新连接wifi即可,
		   而不必亲自动手,在开机自动连接和断开重连方面能节省时间
		 */
		 if(!wlan0_status())
		 {
		    #ifdef DEBUG 
		    printf("wait system to connect target wifi...\n");
		    #endif

		    usleep(DELAY_100MS);
		    continue;
		 }


         #ifdef DEBUG
         printf("wifi connect success!\n");
		 #endif


		 //不同网段对socket连接有影响 
		 wlan0ip      = cmd_system(WLAN0_GET_IP);
		 trycnt       = 0;
		 while((wlan0ip == NULL || strlen(wlan0ip) == 0) && trycnt++ < 5)
		 {
            usleep(DELAY_100MS); 
			wlan0ip   = cmd_system(WLAN0_GET_IP);
		 }
		 if(trycnt >= 5) {
		 	if(wlan0ip == NULL) wlan0ip = "";
		 }
		 

         #ifdef DEBUG
		 printf("wlan0ip=%s\n",wlan0ip);
         #endif

         if(strncmp(SERVER_IP,wlan0ip,9)){
            #ifdef DEBUG
			printf("local ip SERVER_IP are not in lan\n");
            #endif
			continue;
         }

		 memset(data,0,sizeof(data));
		 sprintf(data,"%s&%s",curssid,curpasswd);

		 if(write_file(WIFI_CONFIG_PATH,data,strlen(data)) < 0){
			 #ifdef DEBUG
			 printf("save valid wifi failed!\n");
			 #endif
		 }

         #ifdef DEBUG
         printf("save valid wifi success!\n");
		 #endif


		 //当一直连接成功时却未建立有效连接,iwinfo也要周期性检查 
		 if(iwinfo_nc_cnt++ >= IWINFO_NC_MAX_CNT){
			 iwinfo_nc_cnt        = 0;
			 is_iwinfo_need_check = 1; 

			 #ifdef DEBUG
			 printf("iwinfo period check!\n");
			 #endif

			 continue;
		 }
		 

         trycnt                = 0;
		 is_wifi_info_prepare  = 0;
		 
		 //有新的连接请求就断开当前连接,去连接新的连接
		 while(TRUE)
		 {    
			 if(!is_tcp_client_connect)
			 {
                tcp_client_socket_deinit();

                usleep(DELAY_300MS);

			    if(tcp_client_socket_init() < 0){
					if(trycnt++ < 3){
						continue;
					}else{
						break;
					}
				}
                
				is_tcp_client_connect     = 1;
			 }
			 else
			 {
			     //新的网络请求
	             if(is_wifi_info_prepare){
					 #ifdef DEBUG
					 printf("new wifi connect request...\n");
					 #endif
                     is_tcp_client_connect = 0;
					 break;
				 }


				 /*当用户将设备关闭时,是得不到任何反馈信息的,所以采用状态检测*/
				 //网络断开
				 //连续累加
				 trycnt                    = 0;
                 while(!wlan0_status()){

					 #ifdef DEBUG
					 printf("wlan0_status is test\n");
					 #endif

					 if(trycnt++ >= WIFI_CONNECT_TIMOUT){
						tcp_client_socket_deinit();
						is_tcp_client_connect = 0;

					    #ifdef DEBUG
					    printf("wlan0 status is down\n");
					    #endif
						
						break;
					 }

					 usleep(DELAY_100MS);
				 }

				 //连接断开
				 if(!is_tcp_client_connect){
				 	#ifdef DEBUG
					printf("tcp client disconnect 1\n");
					#endif

					pthread_mutex_lock(&serial_mutex);
				 	serial_send(gd_serial_fd,wifi_connect_failed,sizeof(wifi_connect_failed));
					pthread_mutex_unlock(&serial_mutex);
					
				 	break;
				 }


				 //间接检测tcp是否断开 
				 trycnt                    = 0;
				 tmp_read_cnt              = global_read_cnt;
 
			     while(tmp_read_cnt == global_read_cnt)
                 {
					/*
					#ifdef DEBUG
					printf("tmp_read_cnt=%d,global_read_cnt=%d,trycnt=%d\n",
						    tmp_read_cnt,global_read_cnt,trycnt);
					#endif
					*/
					//等待6s
					if(trycnt++ >= 12)
					{
                        tcp_client_socket_deinit();
						is_tcp_client_connect = 0;

						#ifdef DEBUG
					    printf("wait 6s over...is_tcp_client_connect=%d\n",is_tcp_client_connect);
					    #endif
						break;
					}

				    usleep(DELAY_500MS);
			     } 	



				 //连接断开
				 if(!is_tcp_client_connect){
				 	#ifdef DEBUG
					printf("tcp client disconnect 2\n");
					#endif

					pthread_mutex_lock(&serial_mutex);
				 	serial_send(gd_serial_fd,wifi_connect_failed,sizeof(wifi_connect_failed));
					pthread_mutex_unlock(&serial_mutex);
					
				 	break;
				 }

			 }


			 //正常连接状态需要休眠 
			 usleep(DELAY_100MS);
			 
		 }
	 }

	 pthread_detach(pthread_self()); 
}

网络连接的认证,握手,同步,加解密,双向数据透传管理


//负责client socket的连接初始化
int tcp_client_socket_init()
{
	static pthread_t send_t, rec_t;
	struct sockaddr_in serv_addr;
	UI8 tcprxbuf[RECV_LENGTH];
	int readlen;
	int options = 1;
	void*retcode = NULL;


    /**
	重新连接时不需要反复分配socket句柄 
	*/
    if(gd_sock_client == -1){

		 #ifdef DEBUG
		 printf("new socket handler create...\n");
		 #endif

	     gd_sock_client                      = socket(AF_INET, SOCK_STREAM, 0);
    }


	if(gd_sock_client < 0){
		#ifdef DEBUG
		printf("The client socket is not create!\n");
		#endif
		return -1;
	}

	memset(&serv_addr, 0, sizeof(serv_addr));

	serv_addr.sin_family                      = AF_INET;
	serv_addr.sin_addr.s_addr                 = inet_addr(SERVER_IP);
	serv_addr.sin_port                        = htons(SERVER_PORT);



	if (connect(gd_sock_client, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0){

		//global_tcp_close(gd_sock_client);
		//gd_sock_client = -1;

		#ifdef DEBUG
		printf("The tcp client connect is not build!\n");
		#endif

		return -1;
	}



    //配置socketfd阻塞属性
	//fcntl(gd_sock_client,F_SETFL,fcntl(gd_sock_client,F_GETFL,0) & ~O_NONBLOCK);
	if(setsockopt(gd_sock_client, IPPROTO_TCP, TCP_NODELAY,(char *) &options, sizeof(options)) == -1){

       #ifdef DEBUG
	   printf("setsockopt TCP_NODELAY failed\n");
       #endif 

	   global_tcp_close(gd_sock_client);
	   gd_sock_client = -1;
	  
	   return -1;
	}
	

    //设置tcp心跳保持连接
    if (setsockopt(gd_sock_client, SOL_SOCKET, SO_KEEPALIVE, (void *)&options,sizeof(options)) == -1) {

       #ifdef DEBUG
	   printf("setsockopt SO_KEEPALIVE failed\n");
       #endif 

	   global_tcp_close(gd_sock_client);
	   gd_sock_client = -1;
	  
	   return -1;
    }



    memset(tcprxbuf,0,sizeof(tcprxbuf));		
    //读取连接状态
	readlen                                   = read(gd_sock_client,tcprxbuf,RECV_LENGTH);

	//支持协议
	if(!strcmp(CONNECT_STATUS_ERROR,tcprxbuf)){
		
		global_tcp_close(gd_sock_client);
		gd_sock_client = -1;
		
		#ifdef DEBUG
		printf("socket connect status:%s\n",CONNECT_STATUS_ERROR);
		#endif
        return -1;
	}else if(!strcmp(CONNECT_STATUS_SUCCESS,tcprxbuf)){
		#ifdef DEBUG
        printf("socket connect status:%s\n",CONNECT_STATUS_SUCCESS);
		#endif
	}else{
	
	    global_tcp_close(gd_sock_client);
		gd_sock_client = -1;

		return -1;
	}


    //协议握手
    if(handle_benchmark_opts() < 0) {

		global_tcp_close(gd_sock_client);
		gd_sock_client = -1;

		return -1;
	}

   
    if(handle_comm_protocol() < 0) {

		global_tcp_close(gd_sock_client);
		gd_sock_client = -1;

		return -1;
	}


    alarm_cnt = 0;


	timer_setup();

    bm_calibrate_cnt = 0;
	global_read_cnt  = 0;


    //清空缓冲队列
	tcflush(gd_serial_fd,TCIFLUSH);
	tcflush(gd_serial_fd,TCOFLUSH); 

	pthread_mutex_lock(&inqueue_mutex);
	set_clear();
	pthread_mutex_unlock(&inqueue_mutex);


    //
    if(is_send_stream_runing)
    {
 	    pthread_cancel(send_t);
	    pthread_join(send_t,retcode);
		
		usleep(DELAY_100MS);

		#ifdef DEBUG
	    printf("send_t thread exit code=%d\n",(int)retcode); 
		#endif
    }
    
	is_send_stream_break                      = 0;  
	if (pthread_create(&send_t, NULL, tcp_send_stream, NULL) != 0){

        is_send_stream_break                  = 1;  
        global_tcp_close(gd_sock_client);
		gd_sock_client = -1;
		
		#ifdef DEBUG
		printf("The thread of send is not create!\n");
	    #endif
		return -1;
	}

	
    
	if(is_recv_stream_runing)
	{
 	    pthread_cancel(rec_t);
	    pthread_join(rec_t,retcode);

		usleep(DELAY_100MS);

		#ifdef DEBUG
	    printf("rec_t thread exit code=%d\n",(int)retcode);	
		#endif
	}
	
    is_recv_stream_break                      = 0;
	if (pthread_create(&rec_t, NULL, tcp_recv_stream, NULL) != 0){

        is_recv_stream_break                  = 1;
		global_tcp_close(gd_sock_client);
		gd_sock_client = -1;
		
		#ifdef DEBUG
		printf("The thread of rec is not create!\n");
		#endif
		return -1;
	}
	

	#ifdef DEBUG
	printf("tcp connect server ok!\n");
	#endif

    pthread_mutex_lock(&serial_mutex);
	serial_send(gd_serial_fd,wifi_connect_ok,sizeof(wifi_connect_ok));
    pthread_mutex_unlock(&serial_mutex);
	
	return 0;
}

双向透传数据上行和下行任务


//负责tcp socket的全部发送任务
void* tcp_send_stream(void*param)
{
	UI8*sendata;
    UI8 sendatalen;
	UI8 is_alloc;

    is_send_stream_runing    =  1;

	while (!is_send_stream_break)
	{
        if(gd_sock_client != -1 && is_tcp_client_connect && !is_empty()){

            pthread_mutex_lock(&inqueue_mutex);
			out_queue(&sendata,&sendatalen,&is_alloc);
			pthread_mutex_unlock(&inqueue_mutex);

            if(sendata != NULL && sendatalen > 0){

			   if(tcp_data_io_write(gd_sock_client,sendata,sendatalen) < 0)
			   {

			      #ifdef DEBUG
				  printf("tcp_data_io_write failed\n");
				  #endif

				  if(gd_sock_client != -1)
				     global_tcp_close(gd_sock_client);

			      is_send_stream_break   = 1;
				  is_recv_stream_break   = 1;
				  gd_sock_client         = -1;
				  is_tcp_client_connect  = 0;

				  //对于动态分配的内存需要手动释放
				  if(is_alloc)
			      {
			         buffree(sendata);
			      }
				  
				  break;
			   }


			   if(is_alloc)
			   {
			      buffree(sendata);
			   }
            }
		}
        else{

		   usleep(DELAY_1MS);
        }
	}


    /**
		创建一个线程默认的状态是joinable, 如果一个线程结束运行但没有被join,
		则它的状态类似于进程中的Zombie Process,
		即还有一部分资源没有被回收(退出状态码),
		所以创建线程者应该调用pthread_join来等待线程运行结束,
		并可得到线程的退出代码,回收其资源(类似于wait,waitpid) 
		但是调用pthread_join(pthread_id)后,如果该线程
		没有运行结束,
		调用者会被阻塞,在有些情况下我们并不希望如此,
		比如在Web服务器中当主线程为每个新来的链接创建一个子线程进行处理的时候,
		主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的链接),
		这时可以在子线程中加入代码 
		pthread_detach(pthread_self()) 
		或者父线程调用 
		pthread_detach(thread_id)(非阻塞,可立即返回) 
		这将该子线程的状态设置为detached,则该线程运行结束后会自动释放所有资源。 
	*/
    pthread_detach(pthread_self());

    is_send_stream_runing   = 0;

	#ifdef DEBUG
	printf(".........tcp_send_stream exit............\n");
	#endif
}





//负责tcp socket的全部接收任务
void* tcp_recv_stream(void*param)
{
    UI8 tcprxbuf[RECV_LENGTH]={0};
    int count;
	int try_cnt;
	
	is_recv_stream_runing     = 1;

	while (!is_recv_stream_break)
	{	
		count = read(gd_sock_client, tcprxbuf, RECV_LENGTH);
		
		if (count < 0) {
			if (errno == EAGAIN || errno == EWOULDBLOCK) {
				continue;
			}

	        #ifdef DEBUG
			printf("tcp_recv_stream count < 0\n");
	        #endif

			/* Got an error on the read, shut down the port. */
			#if 1
			
				if(gd_sock_client != -1)
				   global_tcp_close(gd_sock_client);

				is_send_stream_break  = 1;
				is_recv_stream_break  = 1;
				gd_sock_client        = -1;
				is_tcp_client_connect = 0;

				break;
			#endif
		} 
		else if (count == 0) {
		/* The other end closed the port, shut it down. */

	        #ifdef DEBUG
			printf("tcp_recv_stream count==0\n");
	        #endif

            if(gd_sock_client != -1)
		       global_tcp_close(gd_sock_client);

		    is_send_stream_break  = 1;
		    is_recv_stream_break  = 1;
			gd_sock_client        = -1;
		    is_tcp_client_connect = 0;
		    break;
		}

#if 0
        #ifdef DEBUG
        printf("tcp_recv_stream:");
        print0x(tcprxbuf,count);
        #endif
#endif

        /
		//长度限制
	   	UI8  buf_len        = count;
		if(buf_len < PROTOCOL_MIN_LEN || buf_len > PROTOCOL_MAX_LEN) continue;

        //向手机转发 
        /*if(gd_local_mobile_client != -1){
           tcp_data_io_write(gd_local_mobile_client,tcprxbuf,buf_len);
        }*/
		
		
		//异或解密
	    UI8* decbuf         = decode_protocol(tcprxbuf,buf_len);


		//校验
	    UI32 sam            = check_sam(decbuf,buf_len);
		UI32 decbufsam      = decbuf[PROTOCOL_SAMH_INDEX(buf_len)] << 8 | decbuf[PROTOCOL_SAML_INDEX(buf_len)];

#if 0
	    #ifdef DEBUG
		print0x(decbuf,buf_len);
        printf("sam=%08x,decbufsam=%08x\n",sam,decbufsam);
		#endif
#endif
		
		if(sam        != decbufsam) continue;


	    //平台命令过滤
		if(handle_platform_opts(decbuf,buf_len) >= 0) continue;


		//mavlink接收与校验
		UI8*prxmsg;
		UI8 retval;
		UI8 tmplen              = buf_len - PROTOCOL_EXTRA_LEN;

		status_tcp.parse_state  = MAVLINK_PARSE_STATE_IDLE;
	
		while(tmplen--)
	    {
		    retval              = Mavlink_Frame_Char_Buffer(&rxmsg_tcp,&status_tcp,*decbuf++,TRUE);
			
			if(MAVLINK_FRAMING_INCOMPLETE   == retval)
				continue;
			else if(MAVLINK_FRAMING_BAD_CRC == retval)
				break;
			else
			{
				prxmsg          = (UI8*)&rxmsg_tcp + CHECKSUM_OFFSET_LEN;
				break;
			}
		}

#if 0
        #ifdef DEBUG
        printf("tcp_recv_stream retval=%d,tmplen=%d\n",retval,tmplen);
		print0x(prxmsg,buf_len - PROTOCOL_EXTRA_LEN);
		#endif
#endif

        if(retval == MAVLINK_FRAMING_BAD_CRC) continue;

	    //加强协议完整检测
		if(!(tmplen == 0 && retval == MAVLINK_FRAMING_OK)) continue;
	    
	  
        buf_len      -= PROTOCOL_EXTRA_LEN;
        //远程应答回复指令过滤 
		//if(!(buf_len >= NON_PAYLOAD_LEN && prxmsg[5] == PROTOCOL_CUSTOM_ECHO_CTL)) continue;
 
	    prxmsg[PROTOCOL_MAVLINK_SAMH_INDEX(buf_len)] = MAVLINK_TAIL_REPLACE_CKA;
		prxmsg[PROTOCOL_MAVLINK_SAML_INDEX(buf_len)] = MAVLINK_TAIL_REPLACE_CKB;

        //统计
        global_read_cnt++;

        try_cnt = 0;
try_ser_write:
	    pthread_mutex_lock(&serial_mutex);
        count = serial_send(gd_serial_fd,prxmsg,buf_len);
		pthread_mutex_unlock(&serial_mutex);
		
		if(count < 0 && try_cnt++ < 3) goto try_ser_write; 
	}


     //防止内存泄露
	//pthread_detach(pthread_self()); 

    pthread_detach(pthread_self()); 


    is_recv_stream_runing     = 0;

	#ifdef DEBUG
	printf(".........tcp_recv_stream exit............\n");
	#endif
}






check_tcp_close_wait.sh在后台监听由服务端异常导致的情况。

#轮询检查CLOSE_WAIT,重启堵塞进程
while true
do
   pid=$(netstat -anp | grep 192.168.2.1:16888 | grep CLOSE_WAIT | awk '{print $7}' | cut -d \/ -f1 | grep -oE "[[:digit:]]{1,}")

   if [ ! -n "$pid" ]; then
  	 echo "check_tcp_close_wait IS NULL"
   else
     killall -9 ser2tcpclient
 	 sleep 1
 	 ser2tcpclient &
  
     echo "check_tcp_close_wait NOT NULL"
   fi

   sleep 3
done

小结

完整源码

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我理解了你的问题。下面是Java Telnet透传OpenWRT串口设置,以及串口TCP端口Ser2net透传设置的步骤。 Java Telnet透传: 1. 首先,你需要安装Java开发环境(JDK)和Java Telnet库。 2. 在Java代码,你需要创建一个TelnetClient对象,并设置连接参数,如IP地址和端口号。 3. 接下来,你需要使用TelnetClient对象的InputStream和OutputStream对象来读取和写入数据。 4. 为了实现透传,你需要将从InputStream读取到的数据写入OutputStream,并将从OutputStream读取到的数据写入InputStream。 OpenWRT串口设置: 1. 通过SSH连接到OpenWRT路由器。 2. 执行以下命令安装串口支持:opkg update && opkg install kmod-usb-serial kmod-usb-serial-ftdi kmod-usb-serial-pl2303 3. 连接USB串口接器,并查看其设备文件名:dmesg | grep tty 4. 根据设备文件名,设置串口参数,如波特率、数据位、停止位和校验位:stty -F /dev/ttyUSB0 115200 cs8 -cstopb -parity 5. 使用cat命令测试串口连接:cat /dev/ttyUSB0 串口TCP端口Ser2net透传设置: 1. 安装Ser2net软件:opkg update && opkg install ser2net 2. 创建Ser2net配置文件:vi /etc/ser2net.conf 3. 在配置文件添加以下内容: 2000:raw:0:/dev/ttyUSB0:115200 8DATABITS NONE 1STOPBIT 这表示将串口设备/dev/ttyUSB0映射到TCP端口2000,并设置波特率为115200、数据位为8位、停止位为1位、校验位为无。 4. 启动Ser2net服务:/etc/init.d/ser2net start 5. 使用Telnet连接到TCP端口2000测试透传连接。 希望这些步骤能够帮助你实现Java Telnet透传OpenWRT串口设置,以及串口TCP端口Ser2net透传设置。如果你有任何问题,请随时问我。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值