IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> STM32 WebSocket Server实现 -> 正文阅读

[网络协议]STM32 WebSocket Server实现

STM32 WebSocket Server实现

1. 介绍

具有以太网接口的STM32芯片(STM32F4, STM32F7, STM32H7等),在实现了TCP Server的基础上,可以通过增加协议处理,实现WebSocket Server。

2. TCP Server的实现

基于STM32及DP83848 PHY的TCP Server的实现,可参考:
https://blog.csdn.net/hwytree/article/details/103547919

基于STM32及LAN8742A/LAN8270A PHY的TCP Server的实现,可参考
https://blog.csdn.net/hwytree/article/details/119839143

3. WebSocket Server的实现

增加websocket.h文件,编写如下:

/*
Note: currently only for single websocket frame communication, can be expanded if necessary.
*/

#include <string.h>
#include <stdio.h>  

#define WS_MIN_LEN_READ 544
#define WS_MAX_LEN_WRITE 256

char g_ws_read_buf[WS_MIN_LEN_READ] = {0};
char g_ws_write_buf[WS_MAX_LEN_WRITE] = {0};
char g_ws_write_buf_t[WS_MAX_LEN_WRITE] = {0};

unsigned short int ws_handshake_done = 0; 
unsigned long long payloadLen = 0;  
unsigned long long pack_data_length;

#ifdef __cplusplus
extern "C"{
#endif
	
#define SHA1CircularShift(bits,word) ((((word) << (bits)) & 0xFFFFFFFF) | ((word) >> (32-(bits)))) 	
const char base[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
	
typedef struct SHA1Context
{  
	unsigned Message_Digest[5];        
	unsigned Length_Low;               
	unsigned Length_High;              
	unsigned char Message_Block[64];   
	int Message_Block_Index;           
	int Computed;                      
	int Corrupted;                     
}SHA1Context; 

int tolower(int c);
int htoi(const char s[],int start,int len);
	
char fetch_sec_key(void); 
char compute_accept_key(void)	;
char shake_hand(void); 
	
void base64_encode(void);  	
char sha1_hash(void);
void SHA1Reset(SHA1Context * context); 
int SHA1Result(SHA1Context * context);
void SHA1Input(SHA1Context * context,const char * message_array,unsigned length);    
void SHA1ProcessMessageBlock(SHA1Context *); 
void SHA1PadMessage(SHA1Context * context); 

char analy_data(void); 
void pack_data(char * message, unsigned long long dn); 


//if error, return 0, else return 1
char fetch_sec_key(void)  
{   
	const char * flag = "Sec-WebSocket-Key: "; 
	char * keyBegin = NULL; 
	int i = 0;	
 
	memset(g_ws_write_buf, '\0', WS_MAX_LEN_WRITE);    

	keyBegin = strstr(g_ws_read_buf, flag);  
	if(! keyBegin)   //w/o effective request head 
	{  
		return 0;  
	}
	
	//w/ effective request head
	keyBegin += strlen(flag);  

	for(i = 0; i < strlen(g_ws_read_buf); i++)  
	{  
		if((keyBegin[i] == 0x0A) || (keyBegin[i] == 0x0D))  //0x0A: new line; 0x0D: return
		{  
			break;  
		}  
		g_ws_write_buf[i] = keyBegin[i];  
	}  

	return 1;  
}  

//if error, return 0, else return 1
char compute_accept_key(void)  
{  
	const char * GUID="258EAFA5-E914-47DA-95CA-C5AB0DC85B11";  	  
	int i = 0, n = 0;   
	
	//websocket key
	if(! fetch_sec_key())
		return 0;

	strcat(g_ws_write_buf, GUID);  

	if(! sha1_hash())
		return 0;
 
	n = strlen(g_ws_write_buf); 
 
	memset(g_ws_read_buf, '\0', WS_MIN_LEN_READ);  

	for(i = 0; i < n; i += 2)  
	{        
		g_ws_read_buf[i / 2] = htoi(g_ws_write_buf, i, 2);      
	}   

	base64_encode();   

	return 1;  
}  

//if error, return 0, else return 1
char shake_hand(void)  
{  
	memset(g_ws_read_buf, '\0', WS_MIN_LEN_READ);  

	sprintf(g_ws_read_buf, "HTTP/1.1 101 Switching Protocols\r\n");  
	sprintf(g_ws_read_buf, "%sUpgrade: websocket\r\n", g_ws_read_buf);  
	sprintf(g_ws_read_buf, "%sConnection: Upgrade\r\n", g_ws_read_buf);  
	sprintf(g_ws_read_buf, "%sSec-WebSocket-Accept: %s\r\n\r\n", g_ws_read_buf, g_ws_write_buf);  

	return 1;
}


/*base64 function*/
void base64_encode(void)   
{    
	int tmp = 0, i = 0;	
	int prepare = 0;     
	int temp = strlen(g_ws_read_buf) % 3;     
	char * f = NULL;   	   
	char changed[4];   

	memset(g_ws_write_buf, '\0', WS_MAX_LEN_WRITE);   
	f = g_ws_write_buf;
	while (tmp < strlen(g_ws_read_buf))   
	{   
		temp = 0;   
		prepare = 0;   
		memset(changed, '\0', 4);   
		while (temp < 3)   
		{      
			if (tmp >= strlen(g_ws_read_buf))   
			{   
				break;   
			}   
			prepare = ((prepare << 8) | (g_ws_read_buf[tmp] & 0xFF));   
			tmp++;   
			temp++;   
		}   
		prepare = (prepare << ((3 - temp) * 8));      
		for (i = 0; i < 4 ;i++ )   
		{   
			if (temp < i)   
			{   
				changed[i] = 0x40;   
			}   
			else   
			{   
				changed[i] = (prepare >> ((3 - i) * 6)) & 0x3F;   
			}
			*f = base[changed[i]];     
			f++;   
		}   
	}   
	*f = '\0';
} 


/*SHA1 function*/
void SHA1Reset(SHA1Context * context)
{
	context->Length_Low             = 0;  
	context->Length_High            = 0;  
	context->Message_Block_Index    = 0;  

	context->Message_Digest[0]      = 0x67452301;  
	context->Message_Digest[1]      = 0xEFCDAB89;  
	context->Message_Digest[2]      = 0x98BADCFE;  
	context->Message_Digest[3]      = 0x10325476;  
	context->Message_Digest[4]      = 0xC3D2E1F0;  

	context->Computed   = 0;  
	context->Corrupted  = 0;  
}  


int SHA1Result(SHA1Context * context)
{
	if (context->Corrupted)
	{  
		return 0;  
	}  
	if (!context->Computed) 
	{  
		SHA1PadMessage(context);  
		context->Computed = 1;  
	}  
	return 1;  
}  


void SHA1Input(SHA1Context * context,const char * message_array,unsigned length)
{  
	if (!length) 
		return;  

	if (context->Computed || context->Corrupted)
	{  
		context->Corrupted = 1;  
		return;  
	}  

	while(length-- && !context->Corrupted)
	{  
		context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF);  

		context->Length_Low += 8;  

		context->Length_Low &= 0xFFFFFFFF;  
		if (context->Length_Low == 0)
		{  
			context->Length_High++;  
			context->Length_High &= 0xFFFFFFFF;  
			if (context->Length_High == 0) context->Corrupted = 1;  
		}  

		if (context->Message_Block_Index == 64)
		{  
			SHA1ProcessMessageBlock(context);  
		}  
		message_array++;  
	}  
}  

void SHA1ProcessMessageBlock(SHA1Context * context)
{  
	const unsigned K[] = {0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 };  
	int         t;                  
	unsigned    temp;               
	unsigned    W[80];              
	unsigned    A, B, C, D, E;      

	for(t = 0; t < 16; t++)
	{  
		W[t] = ((unsigned) context->Message_Block[t * 4]) << 24;  
		W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16;  
		W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8;  
		W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]);  
	}  

	for(t = 16; t < 80; t++)
		W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);  

	A = context->Message_Digest[0];  
	B = context->Message_Digest[1];  
	C = context->Message_Digest[2];  
	D = context->Message_Digest[3];  
	E = context->Message_Digest[4];  

	for(t = 0; t < 20; t++)
	{  
		temp =  SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];  
		temp &= 0xFFFFFFFF;  
		E = D;  
		D = C;  
		C = SHA1CircularShift(30,B);  
		B = A;  
		A = temp;  
	}  
	for(t = 20; t < 40; t++)
	{  
		temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];  
		temp &= 0xFFFFFFFF;  
		E = D;  
		D = C;  
		C = SHA1CircularShift(30,B);  
		B = A;  
		A = temp;  
	}  
	for(t = 40; t < 60; t++)
	{  
		temp = SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];  
		temp &= 0xFFFFFFFF;  
		E = D;  
		D = C;  
		C = SHA1CircularShift(30,B);  
		B = A;  
		A = temp;  
	}  
	for(t = 60; t < 80; t++)
	{  
		temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];  
		temp &= 0xFFFFFFFF;  
		E = D;  
		D = C;  
		C = SHA1CircularShift(30,B);  
		B = A;  
		A = temp;  
	}  
	context->Message_Digest[0] = (context->Message_Digest[0] + A) & 0xFFFFFFFF;  
	context->Message_Digest[1] = (context->Message_Digest[1] + B) & 0xFFFFFFFF;  
	context->Message_Digest[2] = (context->Message_Digest[2] + C) & 0xFFFFFFFF;  
	context->Message_Digest[3] = (context->Message_Digest[3] + D) & 0xFFFFFFFF;  
	context->Message_Digest[4] = (context->Message_Digest[4] + E) & 0xFFFFFFFF;  
	context->Message_Block_Index = 0;  
}  

void SHA1PadMessage(SHA1Context *context)
{  
	if (context->Message_Block_Index > 55)
	{  
		context->Message_Block[context->Message_Block_Index++] = 0x80;  
		while(context->Message_Block_Index < 64)  
			context->Message_Block[context->Message_Block_Index++] = 0;  
		SHA1ProcessMessageBlock(context);  
		while(context->Message_Block_Index < 56) 
			context->Message_Block[context->Message_Block_Index++] = 0;  
	} 
	else
	{  
		context->Message_Block[context->Message_Block_Index++] = 0x80;  
		while(context->Message_Block_Index < 56)
			context->Message_Block[context->Message_Block_Index++] = 0;  
	}  
	context->Message_Block[56] = (context->Length_High >> 24 ) & 0xFF;  
	context->Message_Block[57] = (context->Length_High >> 16 ) & 0xFF;  
	context->Message_Block[58] = (context->Length_High >> 8 ) & 0xFF;  
	context->Message_Block[59] = (context->Length_High) & 0xFF;  
	context->Message_Block[60] = (context->Length_Low >> 24 ) & 0xFF;  
	context->Message_Block[61] = (context->Length_Low >> 16 ) & 0xFF;  
	context->Message_Block[62] = (context->Length_Low >> 8 ) & 0xFF;  
	context->Message_Block[63] = (context->Length_Low) & 0xFF;  

	SHA1ProcessMessageBlock(context);  
}  

//if error, return 0, else return 1
char sha1_hash(void)
{ 
	SHA1Context sha = {0};
	SHA1Reset(&sha);  
	SHA1Input(&sha, g_ws_write_buf, strlen(g_ws_write_buf));  

	if (! SHA1Result(&sha))
	{  
		printf("%s-%d:Could not compute message digest.\n", __func__, __LINE__);  
		return 0;  
	}
	else
	{  
		memset(g_ws_write_buf, '\0', WS_MAX_LEN_WRITE);  
		sprintf(g_ws_write_buf, "%08X%08X%08X%08X%08X", sha.Message_Digest[0],sha.Message_Digest[1],  
				sha.Message_Digest[2],sha.Message_Digest[3],sha.Message_Digest[4]);  

		return 1;  
	}  
}


/*convertion function*/
int tolower(int c)   
{   
	if (c >= 'A' && c <= 'Z')   
	{   
		return c + 'a' - 'A';   
	}   
	else   
	{   
		return c;   
	}   
}   

int htoi(const char s[],int start,int len)   
{   
	int i,j;   
	int n = 0;
	if (s[0] == '0' && (s[1]=='x' || s[1]=='X'))
	{   
		i = 2;   
	}   
	else   
	{   
		i = 0;   
	}   
	i+=start;  
	j=0;  
	for (; (s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'f') || (s[i] >='A' && s[i] <= 'F');++i)   
	{     
		if(j>=len)  
		{  
			break;  
		}  
		if (tolower(s[i]) > '9')   
		{   
			n = 16 * n + (10 + tolower(s[i]) - 'a');   
		}   
		else   
		{   
			n = 16 * n + (tolower(s[i]) - '0');   
		}   
		j++;  
	}   
	return n;   
}   	

/*
Frame format:  
      0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 ......
     +-+-+-+-+-------+-+-------------+-------------------------------+
     |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
     |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
     |N|V|V|V|       |S|             |   (if payload len==126/127)   |
     | |1|2|3|       |K|             |                               |
     +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
     |     Extended payload length continued, if payload len == 127  |
     + - - - - - - - - - - - - - - - +-------------------------------+
     |                               |Masking-key, if MASK set to 1  |
     +-------------------------------+-------------------------------+
     | Masking-key (continued)       |          Payload Data         |
     +-------------------------------- - - - - - - - - - - - - - - - +
     :                     Payload Data continued ...                :
     + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
     |                     Payload Data continued ...                |
     +---------------------------------------------------------------+
*/
char analy_data(void)  
{   
	char fin = 0;
	char maskFlag = 0;
	char masks[4] = {0};  
	char temp[8]; 
	unsigned long long i = 0;


  payloadLen = 0;
	if (strlen(g_ws_read_buf) < 2)   
	{  
    //data len error.
		return 0;  
	}  

	fin = (g_ws_read_buf[0] & 0x80) == 0x80; 
	if (!fin)  
	{  
    //fin error.
		return 0;
	}  

	maskFlag = (g_ws_read_buf[1] & 0x80) == 0x80;   
	if (!maskFlag)  
	{  
    //mask flag error.
		return 0;
	}  

	payloadLen = g_ws_read_buf[1] & 0x7F;  
	if (payloadLen == 126)  
	{        
		memcpy(masks, g_ws_read_buf + 4, 4);        
		payloadLen = (((unsigned short)g_ws_read_buf[2] ) << 8) | ((unsigned short)g_ws_read_buf[3]);      
		memset(g_ws_write_buf, '\0', WS_MAX_LEN_WRITE);  
		memcpy(g_ws_write_buf, g_ws_read_buf + 8, payloadLen);  
	}  
	else if (payloadLen == 127)  
	{  
		memcpy(masks, g_ws_read_buf + 10, 4);    
		for ( i = 0; i < 8; i++)  
		{  
			temp[i] = g_ws_read_buf[2 + i];  
		}   

		memcpy(&payloadLen,temp,8);      
		memset(g_ws_write_buf, '\0', WS_MAX_LEN_WRITE);   
		memcpy(g_ws_write_buf, g_ws_read_buf + 14, payloadLen);//toggle error(core dumped) if data is too long.  
     
	}  
	else  
	{     
		memcpy(masks, g_ws_read_buf + 2, 4);       
		memset(g_ws_write_buf, '\0', WS_MAX_LEN_WRITE);  
		memcpy(g_ws_write_buf, g_ws_read_buf + 6, payloadLen);   
	}  

	memset(g_ws_write_buf_t, '\0', WS_MAX_LEN_WRITE); 
	for (i = 0; i < payloadLen; i++)  
	{  
		g_ws_write_buf_t[i] = (char)(g_ws_write_buf[i] ^ masks[i % 4]);
	}  
	
  //get data: g_ws_write_buf_t w/ data length: payloadLen  
	
	return 1; 
}  

void pack_data(char * message, 	unsigned long long dn)  // message: input; dn: input; len: output
{   
  if (dn<=0) pack_data_length = 0;  
	else if ((dn > 0)&&(dn < 126))  
	{   
		memset(g_ws_write_buf, '\0', WS_MAX_LEN_WRITE);      
		g_ws_write_buf[0] = 0x81;  
		g_ws_write_buf[1] = dn;  
		memcpy(g_ws_write_buf + 2, message, dn);  
		pack_data_length = dn + 2;  
	}  
	else if ((dn >= 126)&&(dn <= 0xFFFF)) 
	{    
		memset(g_ws_write_buf, '\0', WS_MAX_LEN_WRITE);
		g_ws_write_buf[0] = 0x81;  
		g_ws_write_buf[1] = 126;  
		g_ws_write_buf[2] = ((dn >> 8) & 0xFF);  
		g_ws_write_buf[3] = (dn & 0xFF);  
		memcpy(g_ws_write_buf + 4, message, dn);      
		pack_data_length = dn + 4;  
	}  
	else  
	{  
		memset(g_ws_write_buf, '\0', WS_MAX_LEN_WRITE);
		g_ws_write_buf[0] = 0x81;  
		g_ws_write_buf[1] = 127;  
		g_ws_write_buf[2] = ((dn >> 56) & 0xFF);
		g_ws_write_buf[3] = ((dn >> 48) & 0xFF);
		g_ws_write_buf[4] = ((dn >> 40) & 0xFF);
		g_ws_write_buf[5] = ((dn >> 32) & 0xFF);
		g_ws_write_buf[6] = ((dn >> 24) & 0xFF);
		g_ws_write_buf[7] = ((dn >> 16) & 0xFF);
		g_ws_write_buf[8] = ((dn >> 8) & 0xFF);
		g_ws_write_buf[9] = ((dn >> 0) & 0xFF);
		
 
		memcpy(g_ws_write_buf + 10, message, dn);      
		pack_data_length = dn + 10;  
	} 
	

	
	//get data: g_ws_write_buf w/ length: *len
	//*len is essential for byte communication beyond character communication
}  



#ifdef __cplusplus
}
#endif


然后将上述已实现TCP Server的代码中的tcpserver.c进行代码升级,如下:

#include <lwip/sockets.h>
#include <lwip/err.h>
#include <lwip/sys.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>								//包含需要的所有头文件,(实现socket和标准输入输出)
#include "tcpserver.h"
#include "usart.h"
#include "websocket.h"

#define	SERVER_PORT			1030				//配置服务器端口号

extern _Bool TCP_STATUS_UPDATE;
uint8_t data_buffer[WS_MIN_LEN_READ];						//定义接收到的数据Buff大小为100  

//static void tcp_server_thread(void *p_arg)		//定义TCP服务器线程
void tcp_echoserver_init(void *p_arg)
{
	struct sockaddr_in server_addr;				//服务器地址
	struct sockaddr_in conn_addr;				//连接地址
	int sock_fd ;								//服务器的 socked
	int sock_conn;								// 请求的 socked
	socklen_t addr_len;							// 地址长度
	int err;
	int length;

	unsigned int rc;

	ws_handshake_done = 0;

	sock_fd = socket(AF_INET, SOCK_STREAM, 0);		//建立一个新的socket连接
	if (sock_fd < 0)
		{
		  printf("tcp socket error\r\n") ;
		  TCP_STATUS_UPDATE = 0;
		  return;
		}
	else printf("tcp socket ok\r\n") ;

	memset(&server_addr, 0, sizeof(server_addr));				//将服务器地址清空
	server_addr.sin_family = AF_INET;							//地址家族
	server_addr.sin_addr.s_addr =inet_addr("192.168.1.252");				//注意转化为网络字节序
	server_addr.sin_port = htons(SERVER_PORT);					//使用SERVER_PORT指定为程序头设定的端口号
	memset(server_addr.sin_zero,0,sizeof(server_addr.sin_zero));

	err = bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));	//建立绑定
	if (err < 0)															    //如果绑定失败则关闭套接字
	{
			closesocket(sock_fd); 												//关闭套接字
			printf("bind error\r\n");
			TCP_STATUS_UPDATE = 0;
			return;

	}
	else printf("tcp socket bind ok\r\n") ;

	err = listen(sock_fd, 1);									//监听连接请求
	if (err < 0) 												//如果监听失败则关闭套接字
	{
			closesocket(sock_fd); 								//关闭套接字
			printf("listen error\r\n");
			TCP_STATUS_UPDATE = 0;
		    return;

	}
	else printf("tcp socket listen ok\r\n") ;

		addr_len = sizeof(struct sockaddr_in);					//将链接地址赋值给addr_len

		sock_conn = accept(sock_fd, (struct sockaddr *)&conn_addr, &addr_len);	//对监听到的请求进行连接,状态赋值给sock_conn

		if(sock_conn<0)											//状态小于0代表连接故障,此时关闭套接字
		{
			closesocket(sock_fd);
			printf("sock_conn error\r\n");
			TCP_STATUS_UPDATE = 0;
			return;

		}
		else printf("sock_conn ok\r\n");

	while (1)
	{
		memset(data_buffer, 0, sizeof(data_buffer));			//清空接收Buff

		length = recv(sock_conn, (unsigned int *)data_buffer, WS_MIN_LEN_READ, 0);	//将收到的数据放到接收Buff

		if (length>0)
		{

			memset(g_ws_read_buf, '\0', WS_MIN_LEN_READ); 接收Buff的数据转移到数据处理Buff,防止之后数据混乱
			     for (rc=0; rc<length; rc++)
	         {
			       g_ws_read_buf[rc] = data_buffer[rc];
		       }

			if (ws_handshake_done == 0)
			{


				  if (compute_accept_key()==0)  ;  //w/o handshaking request
		    	  else
			     {
					   ws_handshake_done = 1;
					   shake_hand();   /*respond handshare*/
         	           send(sock_conn, g_ws_read_buf,strlen(g_ws_read_buf), 1);
			     }

			}
			else  //after correct handshaking
			{
	         analy_data() ;

			     pack_data(g_ws_write_buf_t, payloadLen) ;

	             send(sock_conn,g_ws_write_buf,pack_data_length, 1);

			}

        }
        else
        {
            if (length <0)
            {
    			closesocket(sock_fd);
    			printf("sock_rev error\r\n");
    			TCP_STATUS_UPDATE = 0;
    			return;

            }
            else if (errno != EINTR)  //(length==0)&&(errno!=EINTR) means socket broke
        	{
        	  printf("tcp link broke\r\n");
        	  printf("%s\r\n",g_ws_read_buf);
        	  ws_handshake_done = 0;

        		err = listen(sock_fd, 1);									//监听连接请求
        		if (err < 0) 												//如果监听失败则关闭套接字
        		{
        				closesocket(sock_fd); 								//关闭套接字
        				printf("listen error\r\n");
        				TCP_STATUS_UPDATE = 0;
        			    return;

        		}
        		else printf("tcp socket listen ok\r\n") ;

        			addr_len = sizeof(struct sockaddr_in);					//将链接地址赋值给addr_len

        			sock_conn = accept(sock_fd, (struct sockaddr *)&conn_addr, &addr_len);	//对监听到的请求进行连接,状态赋值给sock_conn

        			if(sock_conn<0)											//状态小于0代表连接故障,此时关闭套接字
        			{
        				closesocket(sock_fd);
        				printf("sock_conn error\r\n");
        				TCP_STATUS_UPDATE = 0;
        				return;

        			}
        			else  printf("sock_conn ok\r\n");

        	}
        }
        osDelay(1);

	}
}

基于上述代码的实现,上电后STM32 WebSocket Server就运行起来。

4. WebSocket 连接测试

编写测试脚本ws_client_test.html

<p id="info">Status Here</p>
<button onclick="wbst_open()">connect</button>
<input id="wsinput"/>
<button onclick="wbst_send()">send</button>
<button onclick="wbst_close()">close</button>

<script>

    var ws ;
    var ws_address = "ws://192.168.1.252:1030";
    wbst_open = function (){
    ws = new WebSocket(ws_address);
    
        ws.onopen = function(evt) {
 	    console.log("Connection opened");
        document.getElementById("info").innerText = "Connection opened"
        };
     
        ws.onmessage = function(evt) {
	    console.log("Received Message: " + evt.data);
        document.getElementById("info").innerText = "Received Message: " + evt.data
        };
 
        ws.onclose = function(evt) {
	    console.log("Connection closed.");
        document.getElementById("info").innerText = "Connection closed."
        window.location.reload();
        }    
     
    }
    
    wbst_send = function (){
		var message;
		message = document.getElementById("wsinput").value;
		if (message.length != 0) ws.send(message);
		 
    }
 
    wbst_close = function (){
        document.getElementById("info").innerText = "Connection closed."
        ws.close();
        window.location.reload();
   }

</script>

用Chrome浏览器打开:
在这里插入图片描述
点击"connect"后,可以向STM32 Websocket Server发送信息,相关过程跟踪信息在控制台(Console)可以查看到。

–End–

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-22 13:50:08  更:2021-08-22 13:50:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 19:03:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码