在FreeRTOS中使用任务来实现并发处理。例如,定义一个任务来处理TFTP请求: 完整案例代码
时间: 2024-03-12 16:50:31 浏览: 141
以下是一个使用FreeRTOS和lwIP实现的并发处理的TFTP服务器的完整案例代码:
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "queue.h"
#define TFTP_OPCODE_RRQ 1
#define TFTP_OPCODE_DATA 3
#define TFTP_OPCODE_ACK 4
#define TFTP_OPCODE_ERROR 5
#define TFTP_ERROR_FILE_NOT_FOUND 1
#define TFTP_ERROR_ACCESS_VIOLATION 2
#define TFTP_ERROR_DISK_FULL 3
#define TFTP_ERROR_ILLEGAL_OPERATION 4
#define TFTP_ERROR_UNKNOWN_TRANSFER_ID 5
#define TFTP_ERROR_FILE_EXISTS 6
#define TFTP_ERROR_NO_SUCH_USER 7
#define MAX_FILENAME_LEN 128
#define MAX_DATA_LEN 512
static SemaphoreHandle_t file_mutex;
static QueueHandle_t file_data_queue;
static int read_file(const char *filename, unsigned char *buf, int buflen)
{
int fd = open(filename, O_RDONLY);
if (fd < 0) {
return -1;
}
int ret = read(fd, buf, buflen);
close(fd);
return ret;
}
static int write_file(const char *filename, unsigned char *buf, int buflen)
{
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0) {
return -1;
}
int ret = write(fd, buf, buflen);
close(fd);
return ret;
}
static void tftp_task(void *pvParameters)
{
int sockfd = *(int *)pvParameters;
struct sockaddr_in client_addr;
unsigned char buf[1024];
while (1) {
// receive request from client
int len = sizeof(struct sockaddr_in);
int ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr, &len);
if (ret < 0) {
// error handling
}
// process request
unsigned short opcode = ntohs(*(unsigned short *)buf);
char *filename = (char *)&buf[2];
char *mode = filename + strlen(filename) + 1;
switch (opcode) {
case TFTP_OPCODE_RRQ:
{
xSemaphoreTake(file_mutex, portMAX_DELAY);
int data_len = read_file(filename, buf, sizeof(buf));
xSemaphoreGive(file_mutex);
if (data_len < 0) {
buf[1] = TFTP_OPCODE_ERROR;
buf[3] = TFTP_ERROR_FILE_NOT_FOUND;
sendto(sockfd, buf, 4, 0, (struct sockaddr *)&client_addr, sizeof(struct sockaddr_in));
} else {
int block_num = 1;
int data_sent = 0;
while (data_sent < data_len) {
buf[0] = 0;
buf[1] = TFTP_OPCODE_DATA;
*(unsigned short *)&buf[2] = htons(block_num);
memcpy(&buf[4], &buf[data_sent], MAX_DATA_LEN);
int data_to_send = data_len - data_sent;
if (data_to_send > MAX_DATA_LEN) {
data_to_send = MAX_DATA_LEN;
}
sendto(sockfd, buf, data_to_send + 4, 0, (struct sockaddr *)&client_addr, sizeof(struct sockaddr_in));
int ack_len = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr, &len);
if (ack_len < 0) {
// error handling
}
if (ntohs(*(unsigned short *)buf) == TFTP_OPCODE_ACK && ntohs(*(unsigned short *)&buf[2]) == block_num) {
data_sent += MAX_DATA_LEN;
block_num++;
}
}
}
break;
}
case TFTP_OPCODE_DATA:
{
unsigned short block_num = ntohs(*(unsigned short *)&buf[2]);
xQueueSend(file_data_queue, &buf[4], 0);
buf[0] = 0;
buf[1] = TFTP_OPCODE_ACK;
*(unsigned short *)&buf[2] = htons(block_num);
sendto(sockfd, buf, 4, 0, (struct sockaddr *)&client_addr, sizeof(struct sockaddr_in));
break;
}
case TFTP_OPCODE_ERROR:
{
// error handling
break;
}
default:
{
buf[0] = 0;
buf[1] = TFTP_OPCODE_ERROR;
buf[3] = TFTP_ERROR_ILLEGAL_OPERATION;
sendto(sockfd, buf, 4, 0, (struct sockaddr *)&client_addr, sizeof(struct sockaddr_in));
break;
}
}
}
}
int main(int argc, char **argv)
{
file_mutex = xSemaphoreCreateMutex();
file_data_queue = xQueueCreate(10, MAX_DATA_LEN);
struct sockaddr_in server_addr;
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
// error handling
}
memset(&server_addr, 0, sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(69);
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) < 0) {
// error handling
}
xTaskCreate(tftp_task, "tftp_task", 2048, &sockfd, tskIDLE_PRIORITY + 1, NULL);
vTaskStartScheduler();
}
```
此代码实现了一个简单的TFTP服务器,可以处理客户端的读取文件请求和数据传输请求。文件的读写操作使用了互斥量来保证一致性,数据的传输使用了消息队列来传递。
阅读全文