69-recv 和 send 函数

本文详细介绍了recv和send函数在套接字编程中的应用,并解释了它们与read和write函数的区别。重点阐述了flags参数的不同选项及其作用,包括MSG_DONTROUTE、MSG_DONTWAIT、MSG_OOB、MSG_PEEK和MSG_WAITALL等常用标志位。

recv 和 send 函数专门用于套接字描述符的,相比于 read 和 write,前三个参数一模一样。recv 和 send 只多了一个参数 —— flags.

如果你还记得 recvfrom 和 sendto,你应该能回忆起它们也有一个参数 flags,那时候没有讲解这个标志位,是因为放到这篇文章一起讲了。

1. recv 和 send

  • 函数原型
 ssize_t recv(int sockfd, void *buf, size_t len, int flags);
 ssize_t send(int sockfd, const void *buf, size_t len, int flags);
  • 参数 flags

前面的在个参数和 read、write 没有区别,就不多说了,这里重点看 flags 参数。

flags 是一个组合标志选项,因为它的名字是以 s 结尾。它有很多可选项,这里只说常用的几种,更多的选项请参数 man 手册。

选项说明
MSG_DONTROUTE告诉内核目的主机在直连的本地网络上(同一网段),不要使用网关将数据包路由出去 (仅支持 send 和 sendto 函数
MSG_DONTWAIT临时将套接字描述符设置成非阻塞(支持 recv 和 send
MSG_OOB对于 send,表示即将发送带外数据(out-of-band data);对于 recv 来说,表示即将读入带外数据(支持 recv 和 send
MSG_PEEK查看可读取的数据,返回后内核不会将已读取的数据从接收缓冲区中删除。(仅支持 recv 和 recvfrom 函数
MSG_WAITALL指定该标志,就相当于 readn 函数。(仅支持 recv 和 recvfrom 函数

这些标志位对我们来说并没有什么难度,以后我们确实要用到它的时候,再结合代码分析。

2. 总结

  • 理解 recv 和 send 常用的标志位
首先,您需要使用FreeRTOS中的任务来实现并发处理。您可以创建一个任务来处理TFTP请求,然后在任务中使用您的现有函数来实现TFTP服务器。 例如,您可以创建一个名为tftp_task的任务,该任务将在启动时创建一个UDP套接字,并在循环中等待接收来自客户端的TFTP请求。在接收到请求后,该任务将启动一个新的任务来处理该请求,并等待下一个请求。 以下是一个示例代码框架: ``` // TFTP task void tftp_task(void *pvParameters) { struct udp_pcb *pcb; // create UDP socket pcb = udp_new(); // bind socket to port 69 udp_bind(pcb, IP_ADDR_ANY, 69); while(1) { struct pbuf *p; ip_addr_t addr; u16_t port; // wait for incoming packet p = udp_recv(pcb, recv, NULL); // get client address and port addr = *(ip_addr_t *)p->payload; port = *((u16_t *)p->payload + 2); // create new task to handle request xTaskCreate(tftp_request_task, "tftp_request_task", configMINIMAL_STACK_SIZE, (void *)&addr, tskIDLE_PRIORITY + 1, NULL); // free packet buffer pbuf_free(p); } } // TFTP request task void tftp_request_task(void *pvParameters) { ip_addr_t *addr = (ip_addr_t *)pvParameters; // handle TFTP request using existing functions // e.g. send_error(), send_ack(), send_data(), etc. // use mutex/semaphore to synchronize access to shared resources // e.g. file system, memory, etc. } // TFTP timer task void tftp_tmr_task(void *pvParameters) { while(1) { // handle TFTP timer events using existing tftp_tmr() function tftp_tmr(NULL); // delay for 100ms vTaskDelay(pdMS_TO_TICKS(100)); } } // TFTP server initialization err_t tftp_init(const struct tftp_context *ctx) { // create TFTP task xTaskCreate(tftp_task, "tftp_task", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL); // create TFTP timer task xTaskCreate(tftp_tmr_task, "tftp_tmr_task", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL); return ERR_OK; } ``` 请注意,上述代码框架仅供参考,您需要根据自己的实际情况进行调整修改。 在处理TFTP请求时,请确保使用互斥锁或信号量来同步访问共享资源,例如文件系统或内存。这可以防止多个任务同时访问同一资源而导致数据损坏或不一致。 同时,请注意在处理TFTP请求时要处理错误情况,例如超时、丢失的数据包、非法请求等。这可以通过调用send_error()函数来实现。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值