STC单片机+ESP8266+socket服务端:局域网内控制端主动广播的服务发现机制

本搬砖工开始玩串口转wifi传输模块ESP_8266(以前只会JAVA)。前段时间做了个JAVA服务端控制8盏LED亮灭的demo,美中不足是单片机连接服务器需要预先知道部署在内网的IP地址,所以又做了个局域网内上位机与模块相互发现的服务发现程序。
通讯采用上位机主动UDP广播的模式。java服务器和单片机同时开启UDP广播模式。服务端对192.168.1.255(局域网网段广播地址)发送设备寻找命令,单片机收到后获取IP地址,回复设备应答命令,双方确认后,单片机断开UDP连接,作为TCP客户端连接服务器的TCP socket服务端(随服务器运行启动),后续通过TCP请求通信控制单片机的应用功能。

设备端代码:

main.c

#include	"config.h"
#include	"delay.h"
#include	"USART1.h"
//#include	"display.h"
#include <string.h>
#include <stdio.h>

char idata cbuf[16];
char idata remoteIP[32];
unsigned int remotePort;

//串口初始化
  void	UART_config(void)
{
	COMx_InitDefine		COMx_InitStructure;					//结构定义
	COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;		//模式,       UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
	COMx_InitStructure.UART_BRT_Use   = BRT_Timer1;			//使用波特率,   BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
	COMx_InitStructure.UART_BaudRate  = 115200ul;			//波特率, 一般 110 ~ 115200
	COMx_InitStructure.UART_RxEnable  = ENABLE;				//接收允许,   ENABLE或DISABLE
	COMx_InitStructure.BaudRateDouble = DISABLE;			//波特率加倍, ENABLE或DISABLE
	COMx_InitStructure.UART_Interrupt = ENABLE;				//中断允许,   ENABLE或DISABLE
	COMx_InitStructure.UART_Polity    = PolityLow;			//中断优先级, PolityLow,PolityHigh
	COMx_InitStructure.UART_P_SW      = UART1_SW_P36_P37;	//切换端口,   UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17(必须使用内部时钟)
	COMx_InitStructure.UART_RXD_TXD_Short = DISABLE;		//内部短路RXD与TXD, 做中继, ENABLE,DISABLE
	USART_Configuration(USART1, &COMx_InitStructure);		//初始化串口1 USART1,USART2
	
	
}
//检测命令,只检测其中2位即判断接收正确
 bit checkCmdChars(u8 i1,char c1,u8 i2,char c2){
 
	 int i=0,j,k=i2-i1+1;
	 //char cr;
	 //cbuf = (char *)malloc(k * sizeof(char));	 
	 
	 while(1){
	 	 		 
		 while(!RI);
		 RI=0;
		 cbuf[i] = SBUF;
		 

		if(cbuf[i] == c2){
			
			j=((i<k-1)?(i+1):0);
			if(cbuf[j] == c1){
			  break; 
			  
			}
		
		}
		i++;
		if(i>=k){i=0;}

	 }

//	 free(cbuf);
//	 cbuf = NULL;
	 return 1;
 }

//获取收到的信息中的IP与端口(消息格式见ESP8266文档)
bit checkIPport(){
 
	 char i=0;
	 char f = 0;
	 
	 char cr;
	 
	 
	 while(1){

	 	 if(i>=32){
			return 0;
		 }	
		 
		 if(remotePort < 0 || remotePort > 65535){
		  	return 0;
		 }
		 	 
		 while(!RI);
		 RI=0;
		 cr = SBUF;
		 

		if(f==0){
			if(cr == ','){
			  f = 1;
			}
			continue;
		}

		if(f>0 && f<5 && cr>='0' && cr<='9'){
			  remoteIP[i++]=cr;
			  continue;
		   
		}

		if(f>0 && f<4 && cr=='.'){
		   	  f++;
			  remoteIP[i++]=cr;	
			  continue;
			  	
		}
		
		if(f==4 && cr == ','){
			f = 5;
			remoteIP[i++]=0;
			remotePort = 0;
			continue;
		}
		
		if(f==5 && cr>='0' && cr<='9'){
		   remotePort = remotePort*10+cr-'0';
		   continue;
		}

		if(f==5 && cr==':'){
		  return 1;
		}
	   return 0;
	 }


	 return 0;
 }

//比较收到的信息中的IP与端口是否与先前一致(消息格式见ESP8266文档)
bit compIPport(){
 
	 char i=0;
	 char f = 0;
	 
	 char cr;
	 unsigned int port = 0;
	 
	 while(1){
		 		 
	 	 if(i>=32){
			return 0;
		 }	
		  
		 if(port < 0 || port > 65535){
		  	return 0;
		 }
		 	 
		 while(!RI);
		 RI=0;
		 cr = SBUF;
		 
		if(f==0){
		   
			if(cr == ','){
			  
			  f=1;
			}
			continue;
		}

		if(f==1 && cr == ','){
			if(remoteIP[i++]==0){
				f = 2;
				continue;
			}
			return 0;
		}

		if(f==1 && remoteIP[i++]==cr){ 
			if(cr!=0 ){
			  continue;
			}
			return 0;
		}

		if(f==2 && cr>='0' && cr<='9'){
		   port = port*10+cr-'0';
		   continue;
		}

		if(f==2 && cr==':'){
			if(port == remotePort){
			  return 1;
			}
			return 0;
		}
	   return 0;
	 }

	 return 0;
 }


//读取消息中的端口信息,格式:任意命令字符串[端口]
unsigned int readPort(){
 
   unsigned int port = 0;
   char pc = 0;
   char f = 0;
   while(1){
		if(port < 0 || port > 65535){
		  	return 0;
		 }
   		
	   	while(!RI);
	    RI=0;
		pc = SBUF;
		if(f==0 && pc == '['){
		  f=1;
		  continue;
		}
		if(f==1 && pc>='0' && pc<='9'){
		  port=port*10+pc-'0';
		  continue;
		} 
		if(f==1 && pc == ']'){
		 	return port;
		}
		return 0; 	 
   }
   return 0;

}
//ESP_8266模块初始化
void initESP_8266(){
  P0=0x00;
  //收到ready
  checkCmdChars(0,'r',4,'y');
  P0 = 0xfe;
  //收到WIFI GOT IP
  checkCmdChars(0,'W',10,'P');
  P0 = 0xfd;
  delay_ms(200);
  PrintString1("AT+CIPSTART=\"UDP\",\"192.168.1.255\",8093,8093\r\n");
  //收到OK
  checkCmdChars(0,'O',1,'K');
  delay_ms(200);
  PrintString1("AT+CIPDINFO=1\r\n");
  //收到OK
  checkCmdChars(0,'O',1,'K');
  P0 = 0xfb;
  delay_ms(200);

  
}

//等待上位机广播,发现服务
void waitForNet(){
	bit f;
	unsigned int remoteTCPPort =0;
	char xdata concat_name[64];
	while(1)
	{
		P0 = 0xfb;
		//收到广播信息,前缀为+IPD,n,IP,port:
	   checkCmdChars(0,'+',3,'D');
	     while(!RI);
		 RI=0;
	  	 while(!RI);
		 RI=0;
		 f =checkIPport();
		 if(f==0 || remoteIP[0]==0 || remotePort==0){
			continue;
		 }
		 收到findNet
		checkCmdChars(0,'f',4,'N');
		P0 = 0xf7;
		delay_ms(200);
		//发送IamDevice
		sprintf(concat_name,"AT+CIPSEND=9,\"%s\",%u\r\n",remoteIP,remotePort);
		PrintString1(concat_name);
		delay_ms(200);
		PrintString1("IamDevice");
		//收到广播信息,前缀为+IPD,n,IP,port:
		checkCmdChars(0,'+',3,'D');
		while(!RI);
		 RI=0;
	  	 while(!RI);
		 RI=0;
		f =compIPport();
		if(f==0){
		   continue;
		}
		//收到selectYou[端口]
		checkCmdChars(0,'s',6,'Y');
		while(!RI);
		 RI=0;
	  	 while(!RI);
		 RI=0;
		remoteTCPPort = readPort();
		if(remoteTCPPort==0){
			continue;
		}
		P0 = 0xef;
		delay_ms(200);
		//发送acceptYou
		sprintf(concat_name,"AT+CIPSEND=9,\"%s\",%u\r\n",remoteIP,remotePort);
		//PrintString1("AT+CIPSEND=11,\""+remoteIP+"\","+remotePort+"\r\n");
		PrintString1(concat_name);
		delay_ms(200);
		PrintString1("acceptYou");
		checkCmdChars(0,'O',1,'K');
		P0 = 0xdf;
		delay_ms(200);
		PrintString1("AT+CIPCLOSE\r\n");
		checkCmdChars(0,'O',1,'K');
		P0 = 0xbf;
		delay_ms(200);
		//连接TCP服务器
		sprintf(concat_name,"AT+CIPSTART=\"TCP\",\"%s\",%u,1113\r\n",remoteIP,remoteTCPPort);
		//PrintString1("AT+CIPSTART=\"TCP\",\""+remoteIP+"\","+remotePort+",8094\r\n");
		PrintString1(concat_name);
		checkCmdChars(0,'O',1,'K');
		P0 = 0x7f;
		delay_ms(200);
		PrintString1("AT+CIPDINFO=0\r\n");
		checkCmdChars(0,'O',1,'K');
		P0 = 0xff;
		break;

	}
 }

//字符串前缀判断
bit startsWith(const char *pre, const char *str)
{
    size_t lenpre = strlen(pre),
           lenstr = strlen(str);
    return lenstr < lenpre ? 0 : strncmp(pre, str, lenpre) == 0;
}

//判断接收到的命令并点亮LED
void checkRecvStr(char *mystr){
//		int i;
		if(strcmp(mystr,"+IPD,6:lton")==0){
		  P0= 0xff;
		}else if(startsWith("+IPD,7:lton",mystr)){
		  P0 = ~mystr[11];
		}

	  /* if(startsWith("+IPD,"mystr,)){
	   		char num = 0;
			for(i=5;i<16;i++){
				if(mystr[i] != 0)
       			{
		           if ((mystr[i] < '0') || (mystr[i] > '9'))  
		           {                       
		               break;
		           }
		          // num = num * 10 + (mystr[i] - '0');       
       			} 

			}
			if(i>5 && i<11 && mystr[i]==':'){

			  if(mystr[i+1]=='l' && mystr[i+2]=='t' && mystr[i+3]=='o' && mystr[i+4]=='n'){
				P0=0xff;
			  	delay_ms(200);
			 	P0=mystr[i+5];
			  }
			  
			}
		  	
			
	   }  */
}

/**********************************************/
void main(void)
{
	const char xdata RETSTR[5] = {0xCA,0xD5,0xB5,0xBD,0x00};
	u8 p2_buf = 0xFF;
	char idata get_cmd[16];
	
	//CLK_DIV=0x03;

	P0M0=0xff;//		   00000000	  11111111	高阻 下同
	P0M1=0xff;//   
    
	P1M0=0xff;//           11111111  11111111 
	P1M1=0xff;//
	
	P2M0=0xff;//	11111111   111111111
	P2M1=0xff;//常规       
    
	P3M0=0xff; 
	P3M1=0xff;//TXD推挽RXD常规	 11111111   11111111
	
	P4M0=0xff; 
	P4M1=0xff;//11111111   11111111
	
	P5M0=0xff; 
	P5M1=0xff;// 00000000   00000010

	P0 = 0xFF;  //11111111 灭灯

	P0M0=0x00;//		   00000000	  00000000	准双向 数据口
	P0M1=0x00;//

	P2 = 0xFF;//  111111111 按钮初始化

	P2M0=0xff;//  11111111 11111111   按钮 开漏     //	00000000	  00000000 准双向	 控制口
	P2M1=0xff;// 


	P3M0=0xfe; //11111110 11111100
	P3M1=0xfc; //P31TXD10推挽  P30RXD00常规

    recv_buf=0;
//	initLedDisplay();

	UART_config();
	
	EA = 1;

	initESP_8266();

	waitForNet();	
	//发送测试代码
	read_info = 1;
	PrintString1("AT+CIPSEND=4\r\n");
	delay_ms(200);
	PrintString1("testInfo");
	while (1)
	{
	//等待LED点亮控制命令,可改为其他应用代码
		if(get_line == 1){
			strcpy(get_cmd,cmd_str);
		   if(startsWith("+IPD,",get_cmd)){
			  delay_ms(200);
				
			 checkRecvStr(get_cmd);
			 PrintString1("AT+CIPSEND=4\r\n");
			 delay_ms(200);
			 PrintString1(RETSTR);
		   }

		   get_line = 0;
		}

	
	}
}


USART1.c

/*---------------------------------------------------------------------*/
/*改造自STC例程*/
/*串口接收通过/r/n换行符结束,接收一条命令。长度<=15*/
/*超时模式请参考前一篇博客*/
/*---------------------------------------------------------------------*/
#include "USART1.h"
#include "delay.h"
#include "string.h"


COMx_Define	COM1;
//u8 idata send_buf;
u8 recv_buf;
//u8 idata send_buf;
char idata recv_str[16];
char idata cmd_str[16];
u8 recv_index = 0;
bit get_line = 0;
u8 last_buf=0;
bit read_info = 0;





u8 USART_Configuration(u8 UARTx, COMx_InitDefine *COMx)
{
	u32	j;
	
	if(UARTx == USART1)
	{
		COM1.id = 1;
		COM1.TX_read    = 0;
		COM1.TX_write   = 0;
		COM1.B_TX_busy  = 0;
		COM1.RX_Cnt     = 0;
		COM1.RX_TimeOut = 0;
		COM1.B_RX_OK    = 0;
	

		if(COMx->UART_Mode > UART_9bit_BRTx)	return 1;	//模式错误
		if(COMx->UART_Polity == PolityHigh)		PS = 1;	//高优先级中断
		else									PS = 0;	//低优先级中断
		SCON = (SCON & 0x3f) | COMx->UART_Mode;
		if((COMx->UART_Mode == UART_9bit_BRTx) ||(COMx->UART_Mode == UART_8bit_BRTx))	//可变波特率
		{
			j = (MAIN_Fosc / 4) / COMx->UART_BaudRate;	//按1T计算
			if(j >= 65536UL)	return 2;	//错误
			j = 65536UL - j;
			if(COMx->UART_BRT_Use == BRT_Timer1)
			{
				TR1 = 0;
				AUXR &= ~0x01;		//S1 BRT Use Timer1;
				TMOD &= ~(1<<6);	//Timer1 set As Timer
				TMOD &= ~0x30;		//Timer1_16bitAutoReload;
				AUXR |=  (1<<6);	//Timer1 set as 1T mode
				TH1 = (u8)(j>>8);
				TL1 = (u8)j;
				ET1 = 0;	//禁止中断
				TMOD &= ~0x40;	//定时
				INT_CLKO &= ~0x02;	//不输出时钟
				TR1  = 1;
			}
			else if(COMx->UART_BRT_Use == BRT_Timer2)
			{
				AUXR &= ~(1<<4);	//Timer stop
				AUXR |= 0x01;		//S1 BRT Use Timer2;
				AUXR &= ~(1<<3);	//Timer2 set As Timer
				AUXR |=  (1<<2);	//Timer2 set as 1T mode
				TH2 = (u8)(j>>8);
				TL2 = (u8)j;
				IE2  &= ~(1<<2);	//禁止中断
				AUXR &= ~(1<<3);	//定时
				AUXR |=  (1<<4);	//Timer run enable
			}
			else return 2;	//错误
		}
		else if(COMx->UART_Mode == UART_ShiftRight)
		{
			if(COMx->BaudRateDouble == ENABLE)	AUXR |=  (1<<5);	//固定波特率SysClk/2
			else								AUXR &= ~(1<<5);	//固定波特率SysClk/12
		}
		else if(COMx->UART_Mode == UART_9bit)	//固定波特率SysClk*2^SMOD/64
		{
			if(COMx->BaudRateDouble == ENABLE)	PCON |=  (1<<7);	//固定波特率SysClk/32
			else								PCON &= ~(1<<7);	//固定波特率SysClk/64
		}
		if(COMx->UART_Interrupt == ENABLE)	ES = 1;	//允许中断
		else								ES = 0;	//禁止中断
		if(COMx->UART_RxEnable == ENABLE)	REN = 1;	//允许接收
		else								REN = 0;	//禁止接收
		P_SW1 = (P_SW1 & 0x3f) | (COMx->UART_P_SW & 0xc0);	//切换IO
		if(COMx->UART_RXD_TXD_Short == ENABLE)	PCON2 |=  (1<<4);	//内部短路RXD与TXD, 做中继, ENABLE,DISABLE
		else									PCON2 &= ~(1<<4);
		return	0;
	}
	return 3;	//其它错误
}


/*************** 装载串口发送缓冲 *******************************/

void TX1_write2buff(u8 dat)	//写入发送缓冲,指针+1
{
	if(COM1.B_TX_busy == 0)		//空闲
	{  
		COM1.B_TX_busy = 1;		//标志忙
		SBUF = dat;				//触发发送中断
	}
}


void PrintString1(u8 *puts)
{
    for (; *puts != 0;	puts++) { TX1_write2buff(*puts); delay_us(150);}	//遇到停止符0结束
}




/********************* UART1中断函数************************/
void UART1_int (void) interrupt UART1_VECTOR
{
	//u8 last_index;

	if(RI)
	{
		RI = 0;
		if(read_info == 1) 
		{
		   
			
			recv_buf = SBUF;
			if(recv_buf == '\n' && last_buf=='\r'){
			  if(recv_index < 16){
				recv_str[recv_index]=0;
				strcpy(cmd_str,recv_str);
				get_line = 1;
			  }else{
				recv_str[15]=0;
			  }
			  last_buf=0;
			  recv_index = 0;
	
			}else{
			  if(recv_index < 16){
				if(last_buf != 0){
					recv_str[recv_index]=last_buf;
					recv_index++;
				}
			  }
			  last_buf=recv_buf;
			  
			}
		}
		

		

			
		
		COM1.B_RX_OK = 0;
	}

	if(TI)
	{
		TI = 0;
		COM1.B_TX_busy = 0;
		
		
	}
}


usart1.h

/*---------------------------------------------------------------------*/
/*改造自STC例程*/
/*---------------------------------------------------------------------*/
#ifndef __USART_H
#define __USART_H	 

#include	"config.h"

#define	COM_TX1_Lenth	40
#define	COM_RX1_Lenth	40
#define	COM_TX2_Lenth	128
#define	COM_RX2_Lenth	128

#define	USART1	1
#define	USART2	2

#define	UART_ShiftRight	0		//同步移位输出
#define	UART_8bit_BRTx	(1<<6)	//8位数据,可变波特率
#define	UART_9bit		(2<<6)	//9位数据,固定波特率
#define	UART_9bit_BRTx	(3<<6)	//9位数据,可变波特率

#define	UART1_SW_P30_P31	0
#define	UART1_SW_P36_P37	(1<<6)
#define	UART1_SW_P16_P17	(2<<6)	//必须使用内部时钟
#define	UART2_SW_P10_P11	0
#define	UART2_SW_P46_P47	1


#define	TimeOutSet1		5
#define	TimeOutSet2		5

#define	BRT_Timer1	1
#define	BRT_Timer2	2

#define setTimer0() TH0 = 0x00, TL0 = 0x00

typedef struct
{ 
	u8	id;				//串口号

	u8	TX_read;		//发送读指针
	u8	TX_write;		//发送写指针
	u8	B_TX_busy;		//忙标志

	u8 	RX_Cnt;			//接收字节计数
	u8	RX_TimeOut;		//接收超时
	u8	B_RX_OK;		//接收块完成
} COMx_Define; 

typedef struct
{ 
	u8	UART_Mode;			//模式,         UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
	u8	UART_BRT_Use;		//使用波特率,   BRT_Timer1,BRT_Timer2
	u32	UART_BaudRate;		//波特率,       ENABLE,DISABLE
	u8	Morecommunicate;	//多机通讯允许, ENABLE,DISABLE
	u8	UART_RxEnable;		//允许接收,   ENABLE,DISABLE
	u8	BaudRateDouble;		//波特率加倍, ENABLE,DISABLE
	u8	UART_Interrupt;		//中断控制,   ENABLE,DISABLE
	u8	UART_Polity;		//优先级,     PolityLow,PolityHigh
	u8	UART_P_SW;			//切换端口,   UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17(必须使用内部时钟)
	u8	UART_RXD_TXD_Short;	//内部短路RXD与TXD, 做中继, ENABLE,DISABLE

} COMx_InitDefine; 

extern	COMx_Define	COM1,COM2;
extern  u8 recv_buf;
//extern  u8 idata send_buf;
extern char idata recv_str[16];
extern  u8 recv_index;
extern  char idata cmd_str[16];
extern  bit get_line;
extern  bit read_info;

u8	USART_Configuration(u8 UARTx, COMx_InitDefine *COMx);
void TX1_write2buff(u8 dat);	//写入发送缓冲,指针+1
void TX2_write2buff(u8 dat);	//写入发送缓冲,指针+1
void PrintString1(u8 *puts);
void PrintString2(u8 *puts);

void Timer0_init();

//void COMx_write2buff(COMx_Define *COMx, u8 dat);	//写入发送缓冲,指针+1
//void PrintString(COMx_Define *COMx, u8 *puts);

#endif

delay.h, delay.c, config.h, stc15fxxxx.h同STC例程,略。

###################################################################

服务端代码

UdpSocketSender.java

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UdpSocketHandler implements Runnable {

	private DatagramSocket socket;
	
	public UdpSocketHandler(){
		try{
			socket= new DatagramSocket(8091);
			System.out.println("****服务器端已经启动");
		}catch(Exception e){
			e.printStackTrace();
			System.out.println("****服务器端启动失败");
			socket.close();
		}
	}
	

	
	@Override
	public void run() {
		try{
			if(socket != null && !socket.isClosed()){
				UdpSocketSender r = new UdpSocketSender(socket);
				r.setHandler(this);
				Thread handler = new Thread(r);
				
				handler.start();
				while(true){
					if(UdpSocketSender.isGlobeSend == true){
						System.out.println("****服务器等待客户端发送数据");
						byte[] data =new byte[1024];//创建字节数组,指定接收的数据包的大小
						DatagramPacket packet=new DatagramPacket(data, data.length);
						socket.receive(packet);//此方法在接收到数据报之前会一直阻塞
						String info1=new String(data, 0, packet.getLength());
						System.out.println("我是服务器,客户端说:"+info1);
						if("IamDevice".equals(info1)){
							System.out.println("正确的客户端响应参数");
							InetAddress address=packet.getAddress();
							int port=packet.getPort();
							byte[] data2="selectYou[8092]\r\n".getBytes();
							//2.创建数据报,包含响应的数据信息
							DatagramPacket packet2=new DatagramPacket(data2, data2.length, address, port);
							//3.响应客户端
							socket.send(packet2);
							
						}
					}else{
						Thread.sleep(100);
//						try{
//							this.wait(500);
//						}catch(Exception e){
//							//e.printStackTrace();
//						}
						
					}
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}


}

UdpSocketSender.java

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UdpSocketSender implements Runnable {

	public static boolean isGlobeSend = false;
	private static final String udpIP = "192.168.1.255";
	private static final int devUdpPort = 8093;
	private DatagramSocket socket;
	private UdpSocketHandler handler = null;
	
	private UdpSocketSender(){
		
	}
	
	public UdpSocketSender(DatagramSocket socket){
		this.socket = socket;
	}
	
	@Override
	public void run() {
		
		
		try{
			System.out.println("****循环发送udp广播");
			while(true){
				
				
				byte[] data2="findNet\r\n".getBytes();
				//2.创建数据报,包含响应的数据信息
				InetAddress udpAddr = InetAddress.getByName(udpIP); 
				DatagramPacket packet2=new DatagramPacket(data2, data2.length, udpAddr, devUdpPort);
				//3.响应客户端
				socket.send(packet2);
				if(isGlobeSend == false){
//					if(handler != null){
//						handler.notify();
//					}
					isGlobeSend = true;
				}
				
				
				Thread.sleep(1000);
			}
		}catch(Exception e){
			e.printStackTrace();
			isGlobeSend = false;
			socket.close();
		}
		
		
		
	}

	public void setHandler(UdpSocketHandler handler) {
		this.handler = handler;
	}

	

}

TcpSocketThread.java

import java.net.ServerSocket;

import com.geye.wx.utils.constants.BaseConstants;

import ch.qos.logback.core.net.server.Client;


//@Component
//@Scope("singleton")
public class TcpSocketThread implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		if(BaseConstants.isRun == 0){
			BaseConstants.isRun = 1;
			ServerSocket tcpSocket = null;
			try{
				tcpSocket = new ServerSocket(8092);
				while(true){
					BaseConstants.client = tcpSocket.accept();
					System.out.println("客户端连接");
				}
			}catch(Exception e){
				e.printStackTrace();
				try{
					BaseConstants.client.close();
					tcpSocket.close();
					
				}catch(Exception ee){
					ee.printStackTrace();
				}
			}
		}
		
	}

}

启动代码中添加:

		Thread startThread = new Thread(new TcpSocketThread());
        startThread.start();
        Thread udpThread = new Thread(new UdpSocketHandler());
        udpThread.start();

部署在局域网PC,启动服务。
烧写单片机,连接ESP8266模块,上电。

效果是单片机启动后可以找到局域网内部署服务的IP/端口。
用户通过手机或PC访问页面控制灯的亮灭。
以下是服务端控制页面,业余前端水平,css颜值一般般~

不好意思原截图找不到了只好拿个同时代的微信小程序页面应景哈哈哈哈

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值