在编写使用select函数的TCP和UDP回射程序,出现UDP的sendto错误,现象如下:

  • 服务端正常启动后,调用select函数监听TCP和UDP套接字, 可以正常处理TCP请求。

  • UDP客户端可以连接到服务端,但接收标准输入后无回显,阻塞于recvfrom。

经排查,发现服务端处理UDP请求的代码有问题,如下:

typedef struct sockaddr SA;
void udp_echo(int udpfd) {
	int n;
	char recvline[MAXLINE];
	struct sockaddr_in cliaddr;
	socklen_t len;
	n = recvfrom(udpfd, recvline, MAXLINE, 0, (SA*)&cliaddr, &len);
	sendto(udpfd, recvline, n, 0, (SA*)&cliaddr, len);

udp_echo函数,先用recvfrom读取UDP客户端发送的字符串,再使用sendto将该字符串送回客户端。代码中没有判断recvfrom, sendto函数的返回值,为了获取出错信息改写如下:

void udp_echo(int udpfd) {
	int n;
	char recvline[MAXLINE];
	struct sockaddr_in cliaddr;
	socklen_t len;
	if((n = recvfrom(udpfd, recvline, MAXLINE, 0, (SA*)&cliaddr, &len)) < 0) {
		err_sys("recvfrom error");
	if(sendto(udpfd, recvline, n, 0, (SA*)&cliaddr, len) != n) {
		printf("error: %s\n", strerror(errno));
		err_sys("sendto error");

再运行程序,输出如下:

$ error: Invalid argument

$ sendto error

错误原因在于cliaddr参数没有初始化。sockaddr_in结构体在使用之前,需要先使用bzero/memset函数初始化为0,否则出现赋值不完整导致参数无效。

  • 变量使用之前最好初始化。

  • 注意判断函数的返回值,可以使用包裹函数。

上文从“UDP发送Hello World”的实例体会了lwIP的使用。在user_udp_init函数中我们按照“创建UDP PCB->绑定本地端口->连接远程主机”的顺序完成初始化,发送时使用send函数将数据发送至连接的主机。 事实上,udp_connect函数的作用只是设置PCB的远程地址,没有产生任何网络流量。lwIP在UDP通信中还有另一个发送函数udp_sendto,本文在... sendto 系统调用原型 sendto( int fd, void * buff, size_t len,unsigned int flags, struct sockaddr *addr,int addr_len) 内核中处理流程: sendto( int fd, void * buff, size_t len,unsigned int flags, struct sockaddr *addr,int addr_len) __sys_sendto(fd, buff, len, flags, NU 图片/在思考的樱木花道UDP(user datagram protocol)用户数据报协议,属于传输层。UDP是面向非连接的协议,它不与对方建立连接,而是直接把数据报发给对方。UDP无需建... UDP不是面向连接的协议,发送数据的时候指定目的地址的信息即可以发送。下面是入口函数的代码。 static int sock_sendto(int fd, void * buff, int len, unsigned flags, struct sockaddr *addr, int addr_len) struct socket *sock; struct file *file;... 功能描述: 发送消息。send只可用于基于连接的套接字,send 和 write唯一的不同点是标志的存在,当标志为0时,send等同于write。sendto 和 sendmsg既可用于无连接的套接字,也可用于基于连接的套接字。除了套接字设置为非阻塞模式,调用将会阻塞直到数据被发送完。 #include #include ssize_t send(int sock vxworks是美国风河公司退出的嵌入式实时操作系统,目前最新版本为vxworks 6.9,开发平台为workbench2.2。网络编程过程中遇到的问题汇总如下: 1. sendto数据发送失败 函数原型: int sendto ( socket s , const void * msg, int len, unsigned int flags, const struct sockadd err_t udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, const ip_addr_t *src_ip) struct udp_hdr *udphdr; err_t err; struct pbuf *q; /* q will be sent down the stack */ u8_t ip_p 函数原型 int sendto (int s, const void *buf, int len, unsigned int flags, const struct sockaddr *to, int tolen); int recvfrom(int s, void *buf, int len, unsigned int flags, struct sockaddr *from, int *f... 很多人会不理解发送速度过快为什么会产生丢包,原因就是UDPSendTo不会造成线程阻塞,也就是说,UDP的SentTo不会像TCP中的SendTo那样,直到数据完全发送才会return回调用函数,它不保证当执行下一条语句时数据是否被发送。编写一个转发模块,虽然没有要求一转多时要达到多少路(不采用组播的情况下,单纯的一路转成多路),但是本着物尽其用的原则,尽可能测试一下极限。设备A ----------------> 转发设备 ----------------> 设备B。