技术标签: c++ c语言 esp8266 学习笔记
关于ESP8266的配网模式,本人实际接触到的配网有smartconfig和零配网模式
1、smartconfig配网需要用户输入热点的SSID和密码,实际上就是手机端、路由器和通信模块三者之间的一种交互方式,在短时间内,是一种相对稳定和安全的方式,让通信模块连接上指定的路由器,进而获取上网的流量,具体详细请自行了解smartconfig工作原理等。
2、零配网相比smartconfig而言就方便很多,实际上就是路由器、通信模块和已经连接联网设备三者之间的联系,比如之前做过的天猫精灵智能灯,使用的是零配网模式,通过天猫精灵音响通过WIFI对设备进行配网,具体详细请自行了解零配网的相关资料
使用ESP8266 进行 SDK 开发,smartconfig微信配网的代码如下
#include "user_config.h" // 用户配置
#include "driver/uart.h" // 串口
#include "c_types.h" // 变量类型
#include "eagle_soc.h" // GPIO函数、宏定义
#include "ip_addr.h" // 被"espconn.h"使用。在"espconn.h"开头#include"ip_addr.h"或#include"ip_addr.h"
#include "espconn.h" // TCP/UDP接口
#include "ets_sys.h" // 回调函数
#include "mem.h" // 内存申请等函数
#include "os_type.h" // os_XXX
#include "osapi.h" // os_XXX、软件定时器
#include "smartconfig.h" // 智能配网
#include "user_interface.h" // 系统接口、system_param_xxx接口、WIFI、RateContro
#define ProjectName "SmartConfig_WeChat" // 工程名宏定义
#define Sector_STA_INFO 0x80 // 【STA参数】保存扇区
struct station_config STA_INFO; // 【STA】参数结构体
os_timer_t OS_Timer_IP; // 软件定时器
struct ip_info ST_ESP8266_IP; // 8266的IP信息
u8 ESP8266_IP[4]; // 8266的IP地址
//==================================================================================
// 毫秒延时函数
//===========================================
void ICACHE_FLASH_ATTR delay_ms(u32 C_time)
{ for(;C_time>0;C_time--)
os_delay_us(1000);
}
//===========================================
// SmartConfig状态发生改变时,进入此回调函数
//--------------------------------------------
// 参数1:sc_status status / 参数2:无类型指针【在不同状态下,[void *pdata]的传入参数是不同的】
//=================================================================================================================
void ICACHE_FLASH_ATTR smartconfig_done(sc_status status, void *pdata)
{
os_printf("\r\n------ smartconfig_done ------\r\n"); // ESP8266网络状态改变
switch(status)
{
// CmartConfig等待
//……………………………………………………
case SC_STATUS_WAIT: // 初始值
os_printf("\r\nSC_STATUS_WAIT\r\n");
break;
//……………………………………………………
// 发现【WIFI信号】(8266在这种状态下等待配网)
//…………………………………………………………………………………………………
case SC_STATUS_FIND_CHANNEL:
os_printf("\r\nSC_STATUS_FIND_CHANNEL\r\n");
os_printf("\r\n---- Please Use WeChat to SmartConfig ------\r\n\r\n");
break;
//…………………………………………………………………………………………………
// 正在获取【SSID】【PSWD】(8266正在抓取并解密【SSID+PSWD】)
//…………………………………………………………………………………………………
case SC_STATUS_GETTING_SSID_PSWD:
os_printf("\r\nSC_STATUS_GETTING_SSID_PSWD\r\n");
// 【SC_STATUS_GETTING_SSID_PSWD】状态下,参数2==SmartConfig类型指针
//-------------------------------------------------------------------
sc_type *type = pdata; // 获取【SmartConfig类型】指针
// 配网方式 == 【ESPTOUCH】
//-------------------------------------------------
if (*type == SC_TYPE_ESPTOUCH)
{ os_printf("\r\nSC_TYPE:SC_TYPE_ESPTOUCH\r\n"); }
// 配网方式 == 【AIRKISS】||【ESPTOUCH_AIRKISS】
//-------------------------------------------------
else
{ os_printf("\r\nSC_TYPE:SC_TYPE_AIRKISS\r\n"); }
break;
//…………………………………………………………………………………………………
// 成功获取到【SSID】【PSWD】,保存STA参数,并连接WIFI
//…………………………………………………………………………………………………
case SC_STATUS_LINK:
os_printf("\r\nSC_STATUS_LINK\r\n");
// 【SC_STATUS_LINK】状态下,参数2 == STA参数结构体指针
//------------------------------------------------------------------
struct station_config *sta_conf = pdata; // 获取【STA参数】指针
// 将【SSID】【PASS】保存到【外部Flash】中
//--------------------------------------------------------------------------
spi_flash_erase_sector(Sector_STA_INFO); // 擦除扇区
spi_flash_write(Sector_STA_INFO*4096, (uint32 *)sta_conf, 96); // 写入扇区
//--------------------------------------------------------------------------
wifi_station_set_config(sta_conf); // 设置STA参数【Flash】
wifi_station_disconnect(); // 断开STA连接
wifi_station_connect(); // ESP8266连接WIFI
os_printf("WIFI Connecting\r\n");
break;
//…………………………………………………………………………………………………
// ESP8266作为STA,成功连接到WIFI
//…………………………………………………………………………………………………
case SC_STATUS_LINK_OVER:
os_printf("\r\nSC_STATUS_LINK_OVER\r\n");
smartconfig_stop(); // 停止SmartConfig,释放内存
wifi_get_ip_info(STATION_IF,&ST_ESP8266_IP); // 获取8266_STA的IP地址
ESP8266_IP[0] = ST_ESP8266_IP.ip.addr; // IP地址高八位 == addr低八位
ESP8266_IP[1] = ST_ESP8266_IP.ip.addr>>8; // IP地址次高八位 == addr次低八位
ESP8266_IP[2] = ST_ESP8266_IP.ip.addr>>16; // IP地址次低八位 == addr次高八位
ESP8266_IP[3] = ST_ESP8266_IP.ip.addr>>24; // IP地址低八位 == addr高八位
os_printf("ESP8266_IP = %d.%d.%d.%d\n",ESP8266_IP[0],ESP8266_IP[1],ESP8266_IP[2],ESP8266_IP[3]);
os_printf("Successfully\r\n");
os_printf("\r\n---- ESP8266 Connect to WIFI Successfully ----\r\n");
//*****************************************************
// WIFI连接成功,执行后续功能。 如:SNTP/UDP/TCP/DNS等
//*****************************************************
break;
//…………………………………………………………………………………………………
}
}
// IP定时检查的回调函数
//========================================================================================================
void ICACHE_FLASH_ATTR OS_Timer_IP_cb(void)
{
u8 S_WIFI_STA_Connect; // WIFI接入状态标志
// 查询STA接入WIFI状态
//-----------------------------------------------------
S_WIFI_STA_Connect = wifi_station_get_connect_status();
//---------------------------------------------------
// Station连接状态表
// 0 == STATION_IDLE -------------- STATION闲置
// 1 == STATION_CONNECTING -------- 正在连接WIFI
// 2 == STATION_WRONG_PASSWORD ---- WIFI密码错误
// 3 == STATION_NO_AP_FOUND ------- 未发现指定WIFI
// 4 == STATION_CONNECT_FAIL ------ 连接失败
// 5 == STATION_GOT_IP ------------ 获得IP,连接成功
//---------------------------------------------------
// 成功接入WIFI
//----------------------------------------------
if( S_WIFI_STA_Connect == STATION_GOT_IP ) // 判断是否获取IP
{
wifi_get_ip_info(STATION_IF,&ST_ESP8266_IP); // 获取8266_STA的IP地址
ESP8266_IP[0] = ST_ESP8266_IP.ip.addr; // IP地址高八位 == addr低八位
ESP8266_IP[1] = ST_ESP8266_IP.ip.addr>>8; // IP地址次高八位 == addr次低八位
ESP8266_IP[2] = ST_ESP8266_IP.ip.addr>>16; // IP地址次低八位 == addr次高八位
ESP8266_IP[3] = ST_ESP8266_IP.ip.addr>>24; // IP地址低八位 == addr高八位
// 显示ESP8266的IP地址
//--------------------------------
os_printf("ESP8266_IP = %d.%d.%d.%d\n",ESP8266_IP[0],ESP8266_IP[1],ESP8266_IP[2],ESP8266_IP[3]);
//---------------
os_printf("\r\n---- ESP8266 Connect to WIFI Successfully ----\r\n");
os_timer_disarm(&OS_Timer_IP); // 关闭定时器
//*****************************************************
// WIFI连接成功,执行后续功能。 如:SNTP/UDP/TCP/DNS等
//*****************************************************
}
// ESP8266无法连接WIFI
//------------------------------------------------------------------------------------------------
else if( S_WIFI_STA_Connect==STATION_NO_AP_FOUND || // 未找到指定WIFI
S_WIFI_STA_Connect==STATION_WRONG_PASSWORD || // WIFI密码错误
S_WIFI_STA_Connect==STATION_CONNECT_FAIL ) // 连接WIFI失败
{
os_timer_disarm(&OS_Timer_IP); // 关闭定时器
os_printf("\r\n---- S_WIFI_STA_Connect=%d-----------\r\n",S_WIFI_STA_Connect);
os_printf("\r\n---- ESP8266 Can't Connect to WIFI-----------\r\n");
// 微信智能配网设置
//…………………………………………………………………………………………………………………………
//wifi_set_opmode(STATION_MODE); // 设为STA模式 //【第①步】
smartconfig_set_type(SC_TYPE_AIRKISS); // ESP8266配网方式【AIRKISS】//【第②步】
smartconfig_start(smartconfig_done);// 进入【智能配网模式】,并设置回调函数//【第③步】
}
}
// 软件定时器初始化(ms毫秒)
//========================================================================================
void ICACHE_FLASH_ATTR OS_Timer_IP_Init(u32 time_ms, u8 time_repetitive)
{
os_timer_disarm(&OS_Timer_IP); // 关闭定时器
os_timer_setfn(&OS_Timer_IP,(os_timer_func_t *)OS_Timer_IP_cb, NULL); // 设置定时器
os_timer_arm(&OS_Timer_IP, time_ms, time_repetitive); // 使能定时器
}
// user_init:entry of user application, init user function here
//=================================================================================================
void ICACHE_FLASH_ATTR user_init(void)
{
uart_init(115200,115200); // 初始化串口波特率
os_delay_us(10000); // 等待串口稳定
os_printf("\r\n=================================================\r\n");
os_printf("\t Project:\t%s\r\n", ProjectName);
os_printf("\t SDK version:\t%s", system_get_sdk_version());
os_printf("\r\n=================================================\r\n");
// ESP8266读取【外部Flash】中的【STA参数】(SSID/PASS),作为STA,连接WIFI
//………………………………………………………………………………………………………………………………
os_memset(&STA_INFO,0,sizeof(struct station_config)); // STA_INFO = 0
spi_flash_read(Sector_STA_INFO*4096,(uint32 *)&STA_INFO, 96);
// 读出【STA参数】(SSID/PASS)
STA_INFO.ssid[31] = 0; // SSID最后添'\0'
STA_INFO.password[63] = 0; // APSS最后添'\0'
os_printf("\r\nSTA_INFO.ssid=%s\r\nSTA_INFO.password=%s\r\n",STA_INFO.ssid,STA_INFO.password);
wifi_set_opmode(0x01); // 设置为STA模式,并保存到Flash
wifi_station_set_config(&STA_INFO); // 设置STA参数
wifi_station_connect(); // ESP8266连接WIFI(这里,此句可省)
OS_Timer_IP_Init(1000,1); // 定时查询8266连接WIFI情况
}
至此,配网完成!
--2022-4-18补充,配网完成后我们应该怎么使用呢,这里列举下Smartconfig后进行云服务器TCP连接,然后TCP使用接收数据后返回数据控制板载LED灯的亮灭,每1秒发送一次,简易版本
ESP8266程序如下
#include "user_config.h"
#include "driver/uart.h"
#include "c_types.h"
#include "eagle_soc.h"
#include "ip_addr.h"
#include "espconn.h"
#include "ets_sys.h"
#include "mem.h"
#include "os_type.h"
#include "osapi.h"
#include "smartconfig.h"
#include "user_interface.h"
#define ProjectName "SmartConfig_TCP_LED"
#define Sector_STA_INFO 0x80
#define LED_ON GPIO_OUTPUT_SET(GPIO_ID_PIN(4),0) // LED亮
#define LED_OFF GPIO_OUTPUT_SET(GPIO_ID_PIN(4),1) // LED灭
struct espconn ST_NetCon;
struct station_config STA_INFO;
os_timer_t OS_Timer_IP;
os_timer_t Data_send;
struct ip_info ST_ESP8266_IP;
u8 ESP8266_IP[4];
u8 C_LED_Flash = 0;
unsigned char data[2];
u8 numbertime=0;
void ICACHE_FLASH_ATTR delay_ms(u32 C_time)
{ for(;C_time>0;C_time--)
os_delay_us(1000);
}
void ICACHE_FLASH_ATTR ESP8266_WIFI_Send_Cb_JX(void *arg)
{
os_printf("\nESP8266_WIFI_Send_OK\n");
}
// 成功接收网络数据的回调函数【参数1:网络传输结构体espconn指针、参数2:网络传输数据指针、参数3:数据长度】
//=========================================================================================================
void ICACHE_FLASH_ATTR ESP8266_WIFI_Recv_Cb_JX(void * arg, char * pdata, unsigned short len)
{
struct espconn * T_arg = arg; // 缓存网络连接结构体指针
// 根据数据设置LED的亮/灭
//-------------------------------------------------------------------------------
if(pdata[0] == 'k' || pdata[0] == 'K') LED_ON; // 首字母为'k'/'K',灯亮
else if(pdata[0] == 'g' || pdata[0] == 'G') LED_OFF; // 首字母为'g'/'G',灯灭
os_printf("\nESP8266_Receive_Data = %s\n",pdata); // 串口打印接收到的数据
espconn_send(T_arg,"ESP8266_WIFI_Recv_OK",os_strlen("ESP8266_WIFI_Recv_OK")); // 向对方发送应答
}
// TCP连接断开成功的回调函数
//================================================================
void ICACHE_FLASH_ATTR ESP8266_TCP_Disconnect_Cb_JX(void *arg)
{
os_printf("\nESP8266_TCP_Disconnect_OK\n");
}
// TCP连接建立成功的回调函数
//====================================================================================================================
void ICACHE_FLASH_ATTR ESP8266_TCP_Connect_Cb_JX(void *arg)
{
espconn_regist_sentcb((struct espconn *)arg, ESP8266_WIFI_Send_Cb_JX); // 注册网络数据发送成功的回调函数
espconn_regist_recvcb((struct espconn *)arg, ESP8266_WIFI_Recv_Cb_JX); // 注册网络数据接收成功的回调函数
espconn_regist_disconcb((struct espconn *)arg,ESP8266_TCP_Disconnect_Cb_JX); // 注册成功断开TCP连接的回调函数
os_printf("\n--------------- ESP8266_TCP_Connect_OK ---------------\n");
// 也可以不打招呼,因为TCP本身就是握手建立连接。只要TCP连接建立,TCP_Server就已经知道TCP_Client的信息
//----------------------------------------------------------------------------------------------------
espconn_send((struct espconn *)arg,"Hello,I am ESP8266",os_strlen("Hello,I am ESP8266")); // 打招呼
}
// TCP连接异常断开时的回调函数【ESP8266作为TCP_Client,连接TCP_Server失败,也会进入此函数】
//==========================================================================================
void ICACHE_FLASH_ATTR ESP8266_TCP_Break_Cb_JX(void *arg,sint8 err)
{
os_printf("\nESP8266_TCP_Break\n");
espconn_connect(&ST_NetCon); // 连接TCP-server
}
//==================================================================================================
void ICACHE_FLASH_ATTR ESP8266_NetCon_Init_JX()
{
// �ṹ�帳ֵ
//--------------------------------------------------------------------------
ST_NetCon.type = ESPCONN_TCP;
ST_NetCon.proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp)); // 开辟内存
//本人的阿里云服务器 TCP端口50007
ST_NetCon.proto.tcp->local_port = 8266 ; // 本地端口
ST_NetCon.proto.tcp->remote_port = 50007; // 远程端口
ST_NetCon.proto.tcp->remote_ip[0] = 47; //服务器IP地址
ST_NetCon.proto.tcp->remote_ip[1] = 102;
ST_NetCon.proto.tcp->remote_ip[2] = 138;
ST_NetCon.proto.tcp->remote_ip[3] = 197;
// 注册连接成功回调函数、异常断开回调函数
//--------------------------------------------------------------------------------------------------
espconn_regist_connectcb(&ST_NetCon, ESP8266_TCP_Connect_Cb_JX); // 注册TCP连接成功建立的回调函数
espconn_regist_reconcb(&ST_NetCon, ESP8266_TCP_Break_Cb_JX); // 注册TCP连接异常断开的回调函数
// 连接 TCP server
//----------------------------------------------------------
espconn_connect(&ST_NetCon); // 连接TCP-server}
}
void ICACHE_FLASH_ATTR smartconfig_done(sc_status status, void *pdata)
{
os_printf("\r\n------ smartconfig_done ------\r\n");
switch(status)
{
case SC_STATUS_WAIT: // ��ʼֵ
os_printf("\r\nSC_STATUS_WAIT\r\n");
break;
case SC_STATUS_FIND_CHANNEL:
os_printf("\r\nSC_STATUS_FIND_CHANNEL\r\n");
os_printf("\r\n---- Please Use WeChat to SmartConfig ------\r\n\r\n");
break;
case SC_STATUS_GETTING_SSID_PSWD:
os_printf("\r\nSC_STATUS_GETTING_SSID_PSWD\r\n");
sc_type *type = pdata;
if (*type == SC_TYPE_ESPTOUCH)
{ os_printf("\r\nSC_TYPE:SC_TYPE_ESPTOUCH\r\n"); }
else
{ os_printf("\r\nSC_TYPE:SC_TYPE_AIRKISS\r\n"); }
break;
case SC_STATUS_LINK:
os_printf("\r\nSC_STATUS_LINK\r\n");
struct station_config *sta_conf = pdata;
spi_flash_erase_sector(Sector_STA_INFO);
spi_flash_write(Sector_STA_INFO*4096, (uint32 *)sta_conf, 96);
wifi_station_set_config(sta_conf);
wifi_station_disconnect();
wifi_station_connect();
os_printf("\r\n WIFI \r\n");
ESP8266_NetCon_Init_JX();
espconn_create(&ST_NetCon);
break;
case SC_STATUS_LINK_OVER:
os_printf("\r\nSC_STATUS_LINK_OVER\r\n");
smartconfig_stop();
wifi_get_ip_info(STATION_IF,&ST_ESP8266_IP);
ESP8266_IP[0] = ST_ESP8266_IP.ip.addr;
ESP8266_IP[1] = ST_ESP8266_IP.ip.addr>>8;
ESP8266_IP[2] = ST_ESP8266_IP.ip.addr>>16;
ESP8266_IP[3] = ST_ESP8266_IP.ip.addr>>24;
os_printf("ESP8266_IP = %d.%d.%d.%d\n",ESP8266_IP[0],ESP8266_IP[1],ESP8266_IP[2],ESP8266_IP[3]);
for(; C_LED_Flash<=5; C_LED_Flash++)
{
GPIO_OUTPUT_SET(GPIO_ID_PIN(4),(C_LED_Flash%2));
delay_ms(100);
}
os_printf("\r\n---- ESP8266 Connect to WIFI Successfully ----\r\n");
os_timer_disarm(&OS_Timer_IP);
ESP8266_NetCon_Init_JX();
break;
}
}
//========================================================================================================
void ICACHE_FLASH_ATTR OS_Timer_IP_cb(void)
{
u8 S_WIFI_STA_Connect;
S_WIFI_STA_Connect = wifi_station_get_connect_status();
system_soft_wdt_feed();
if( S_WIFI_STA_Connect == STATION_GOT_IP ) // �ж��Ƿ��ȡIP
{
wifi_get_ip_info(STATION_IF,&ST_ESP8266_IP); // ��ȡ8266_STA��IP��ַ
ESP8266_IP[0] = ST_ESP8266_IP.ip.addr; // IP��ַ�߰�λ == addr�Ͱ�λ
ESP8266_IP[1] = ST_ESP8266_IP.ip.addr>>8; // IP��ַ�θ߰�λ == addr�εͰ�λ
ESP8266_IP[2] = ST_ESP8266_IP.ip.addr>>16; // IP��ַ�εͰ�λ == addr�θ߰�λ
ESP8266_IP[3] = ST_ESP8266_IP.ip.addr>>24; // IP��ַ�Ͱ�λ == addr�߰�λ
for(; C_LED_Flash<=5; C_LED_Flash++)
{
GPIO_OUTPUT_SET(GPIO_ID_PIN(4),(C_LED_Flash%2));
delay_ms(100);
}
os_timer_disarm(&OS_Timer_IP);
ESP8266_NetCon_Init_JX();
}
else if( S_WIFI_STA_Connect==STATION_NO_AP_FOUND || // δ�ҵ�ָ��WIFI
S_WIFI_STA_Connect==STATION_WRONG_PASSWORD || // WIFI�������
S_WIFI_STA_Connect==STATION_CONNECT_FAIL ) // ����WIFIʧ��
{
os_timer_disarm(&OS_Timer_IP);
smartconfig_set_type(SC_TYPE_AIRKISS);
smartconfig_start(smartconfig_done);
}
}
void ICACHE_FLASH_ATTR OS_Timer_IP_Init(u32 time_ms, u8 time_repetitive)
{
os_timer_disarm(&OS_Timer_IP);
os_timer_setfn(&OS_Timer_IP,(os_timer_func_t *)OS_Timer_IP_cb, NULL);
os_timer_arm(&OS_Timer_IP, time_ms, time_repetitive); /
}
void ICACHE_FLASH_ATTR LED_Init_JX(void)
{
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4); // GPIO4设为IO口
GPIO_OUTPUT_SET(GPIO_ID_PIN(4),1); // IO4 = 1
}
void ICACHE_FLASH_ATTR user_init(void)
{
uart_init(115200,115200);
os_delay_us(10000);
os_printf("\r\n=================================================\r\n");
os_printf("\t Project:\t%s\r\n", ProjectName);
os_printf("\t SDK version:\t%s", system_get_sdk_version());
os_printf("\r\n=================================================\r\n");
LED_Init_JX(); // 板载LED初始化
//*******************SmartConfig*******************//
os_memset(&STA_INFO,0,sizeof(struct station_config));
spi_flash_read(Sector_STA_INFO*4096,(uint32 *)&STA_INFO, 96);
STA_INFO.ssid[31] = 0;
STA_INFO.password[63] = 0;
os_printf("\r\nSTA_INFO.ssid=%s\r\nSTA_INFO.password=%s\r\n",STA_INFO.ssid,STA_INFO.password);
wifi_set_opmode(0x01);
wifi_station_set_config(&STA_INFO);
//定时器1s延时
OS_Timer_IP_Init(1000,1);
}
//=================================================================================================
/******************************************************************************
* FunctionName : user_rf_cal_sector_set
* Description : SDK just reversed 4 sectors, used for rf init data and paramters.
* We add this function to force users to set rf cal sector, since
* we don't know which sector is free in user's application.
* sector map for last several sectors : ABCCC
* A : rf cal
* B : rf init data
* C : sdk parameters
* Parameters : none
* Returns : rf cal sector
*******************************************************************************/
uint32 ICACHE_FLASH_ATTR user_rf_cal_sector_set(void)
{
enum flash_size_map size_map = system_get_flash_size_map();
uint32 rf_cal_sec = 0;
switch (size_map) {
case FLASH_SIZE_4M_MAP_256_256:
rf_cal_sec = 128 - 5;
break;
case FLASH_SIZE_8M_MAP_512_512:
rf_cal_sec = 256 - 5;
break;
case FLASH_SIZE_16M_MAP_512_512:
case FLASH_SIZE_16M_MAP_1024_1024:
rf_cal_sec = 512 - 5;
break;
case FLASH_SIZE_32M_MAP_512_512:
case FLASH_SIZE_32M_MAP_1024_1024:
rf_cal_sec = 1024 - 5;
break;
case FLASH_SIZE_64M_MAP_1024_1024:
rf_cal_sec = 2048 - 5;
break;
case FLASH_SIZE_128M_MAP_1024_1024:
rf_cal_sec = 4096 - 5;
break;
default:
rf_cal_sec = 0;
break;
}
return rf_cal_sec;
}
void ICACHE_FLASH_ATTR user_rf_pre_init(void){}
服务器端采用python接收发送数据,代码如下
import socketserver
import random
import time
#定义一个类
class MyServer(socketserver.BaseRequestHandler):
#如果handle方法出现报错,则会进行跳过
#setup和finish方法无论如何都会进行执行
#首先执行setup
def setup(self):
pass
#然后执行handle
def handle(self):
conn = self.request #定义连接变量
msg = "当前TCP服务器已连接" #发送消息定义
conn.send(msg.encode()) #消息发送
while True: #进入循环,不断接受客户端的消息
data = conn.recv(1024) #接收客户端信息
print(data.decode()) #接收信息解码decode
if data == b'exit': #接收到exit,则进行循环的退出
break
conn.send(str("guan").encode()) #返回 guan
time.sleep(1) #1s延时
conn.send(str("kai").encode()) #返回 kai
time.sleep(1) #1s延时
conn.close()
#最后执行finish
def finish(self):
pass
if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(("127.0.0.1",50007),MyServer) #创建多线程实例
server.serve_forever() #开启异步多线程,等待连接
Python 程序代码有点粗糙,只是单纯的检验TCP端收发数据的效果而已
文章浏览阅读721次。出处: http://blog.csdn.net/foruok在《Qt Quick 简介》中我们提到 QML 语法和 Json 类似,请参考《Qt on Android: http下载与Json解析》查看 Json 语法。当然这里我们是期望从零开始也能学会 QML ,所以呢,你也可以直接往下看。 版权所有 foruok,转载请注明出处:http://blog.csdn.n_qml返回列表中元素个数
文章浏览阅读807次。tensorflow SessionConfig cluster 源码注释_session options
文章浏览阅读1.2k次。每个人都会有一段异常艰难的时光,在现在生活中,为人处世的最佳境界是不卑不亢。太在乎别人的眼光和评价,只能让自己做事放不开手脚,犹豫不决,失去自我,失去个性,丢失自我的价值。MainActivity.java代码:package siso.handlerdemo;import android.app.NotificationManager;import android.content.Intent;_littlevgl菜单
文章浏览阅读4.1k次。项目Module之间有依赖关系时会导致打jar包失败。比如,athena-eureka、athena-keystone等模块会在pom中依赖athena-common<dependency> <artifactId>athena-common</artifactId> <groupId>com.xxx.xxx</groupId&..._idea 打包springcloud时 单个项目打包出现依赖问题
文章浏览阅读1.3k次。什么是库库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。库有两种:静态库(.a、.lib)和动态库(.so、.dll)。所谓静态、动态是指链接。回顾一下,将一个程序编译成可执行程序的步骤:静态库之所以成为【静_c++ 动态库 静态库创建
文章浏览阅读1.4w次,点赞3次,收藏22次。问题:在请求分页系统中,页表中的辅存始地址是供(D)参考的。 A.页面置换 B.内存分配 C.页面换出 D.页面调入页表项有:|页号|物理块号|状态位P|访问字段A|修改位M|外存地址|各个位的作用:1)状态位P:用于指示该页是否已调入内存,供程序访问时参考; 2)访问字段A:用于记录本页在一段时间内被访问次数,供选择换出页面时参考; 3)修改位M:表示该页在调..._存在位是用于
文章浏览阅读4.4k次,点赞3次,收藏11次。自己动手做制作聊天室。利用C#制作的聊天室。实现QQ和微信聊天的功能。C#课程设计,软件工程课程设计。_聊天软件实现原理
文章浏览阅读472次。磁盘分区有MBR,GPT两种#备份MBR分区表[root@centos8 ~]#dd if=/dev/sda of=/data/dpt.img bs=1 count=64 skip=446 [root@centos8 ~]#scp /data/dpt.img 10.0.0.102: #破坏MBR分区表[root@centos8 ~]#dd if=/dev/zero of=/dev/sda..._phd系统块的大小
文章浏览阅读683次。打印时间 - 错误和正常颜色差异 - 输出打印函数的运行的文件名和行号。_nodejs print
文章浏览阅读129次。1、UUID 获取随机的idimport java.util.UUID;String uuid = UUID.randomUUID().toString(); _java学习地址
文章浏览阅读535次,点赞5次,收藏9次。1. selenium环境安装Selenium环境的安装主要就是安装两样东西: 客户端库 和 浏览器 驱动 。selenium安装 pip install selenium浏览器安装 首选谷歌浏览器驱动安装 驱动版本要和浏览器版本对应2. 基本使用2.1 启动浏览器并搜索网站2.2 定位元素定位元素进行搜索F12 进入开发者模式,找到Elements选择页面元素,鼠标右击检查,找对对应语句,然后根据特征进行查找下面所有定位元素的方法,返回的对象都是·WebElement对_选择网页相应元素
文章浏览阅读7.9w次。1、命令注入(CommandInjection)2、eval注入(EvalInjection)3、客户端脚本攻击(ScriptInsertion)4、跨网站脚本攻击(CrossSiteScripting,XSS)5、SQL注入攻击(SQLinjection)6、跨网站请求伪造攻击(CrossSiteRequestForgeries,CSRF)7、Session会话劫持(SessionHijacking)......_<?php if(isset($_get['c'])){ $arg=$_get['c']; system($arg.">/dev/null 2>&1ka</div>