Linux网络编程关于服务器端问题的解决:linux udp recvfrom: Bad address。linux udp sendto: Message too long

做一个项目时遇到的问题,最终解决了,记录下:

1.问题描述

简单理解就是客户端和服务器之间的socket通信。
客户端就是我自己的Windows电脑,使用的是Qt。
服务器使用的是阿里云的服务器,公网ip,Linux系统,编程也是socket c编程。

先是用的TCP通信传业务数据,一切都正常。
再后来想要用udp通信传视频数据,客户端可以向服务器发送数据并且服务器能收到并显示。
但是服务器向客户端发udp数据时,客户端死活收不到。因为服务器端用的是纯c的socket,想着应该不会出问题。
于是在客户端的qt程序了找了半天bug都没找到原因,整个人心情就不好了,于是将怀疑的目光指向服务器。

2.问题定位

但万事都要讲证据,不能说客户端找不到问题就说服务器有问题,所以解决问题的第一步就是问题定位。
对于数据传输出问题,首先要确定是接收方还是发送方。

好在之前一门课学习了网络抓包,赶紧下载了抓包工具。
首先过滤IP地址,只抓取服务器ip发过来的包和客户端发送出去的包。
在这里插入图片描述
在一通数据交互后,我们可以看到客户端向服务器发送的udp包
在这里插入图片描述
端口号和数据报文都是正确的,服务器也确实是收到了。
问题就是死活都找不到服务器发给客户端的udp包,服务器端已经确认执行了sendto的程序。
说明很大有可能是服务器发送不成功
于是打印出发送的错误:(对,自己之前就是一个憨憨,一个sendto函数直接裸奔,说明错误判断很重要,能避免很多问题,节约很多时间)

//之前是这样写的...裸奔...如果发送没问题还好,有问题就哭死,编程还是不能偷懒,养成好习惯
sendto(sockfd_udp2,udp2_buf,byte_num,0,(struct sockaddr*)&to,len)
//确认是这里出来问题,打印出问题
 if(sendto(sockfd_udp2,udp2_buf,byte_num,0,(struct sockaddr*)&to,len) == -1)
 {
      printf("udp发送错误\n");
      perror("sendto");
 }

在这里插入图片描述

3.sendto:Message too long问题定位

网上一通百度,说是udp的包太大了,要去setsocketopt改缓冲大小,我的包怎么看都只有几个字节呀,怎么会呢,于是用getsocketopt去查udp缓冲区的大小,百度找方法,当时是对照着自己这么写的:

int m;
ret = getsockopt(sockfd_udp2,SOL_SOCKET,SO_SNDBUF,&m,sizeof(m));
 if (ret < 0)
 {
     perror("getsockopt");
 }
 printf("udp发送缓冲长度: %d\n",m);

大佬们能看出来这样写的问题吗?
打印出来是这样的:在这里插入图片描述

4.getsocket: Bad address问题定位

不知道为什么,当时在百度上面都没找到问题,现在去百度发现有人提了…
当时遇到这个问题是懵逼,于是乎就没管这个问题了,又去把接受的函数错误给打印出来(接受是能收到数据的,就单纯想看看有没有问题)

byte_num = recvfrom(sockfd_udp2,udp2_buf,BUFFER_SIZE,0,(struct sockaddr*)&client_device[i].sockaddr_udp1,len);
if (byte_num < 0)
  {
      printf("udp接收错误\n");
      perror("recvfrom");
  }

好家伙。。。虽然能接受到数据,居然也报错了,都是自己偷懒的罪。
在这里插入图片描述

5. Bad address的问题定位

两个完全不同的函数,都出现Bad address,那肯定是传入参数的问题。果不其然…
CSDN上的这句话点醒了我:
在这里插入图片描述

recvfrom (int __fd, void *__restrict __buf, size_t __n, int __flags,
	  __SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len);
sendto (int __fd, const void *__buf, size_t __n,
		       int __flags, __CONST_SOCKADDR_ARG __addr,
		       socklen_t __addr_len);

这两个函数长的是真的像,但是有区别。就在最后一个参数里socklen_t *和socklen_t。
原来就是自己传入的参数有问题

6.Message too long和Bad address问题 的 结论

Bad address:函数传入的参数有问题
Message too long: 传入的长度为-1.因为recvfrom接收错误,导致byte_num = -1.

byte_num = recvfrom(sockfd_udp2,udp2_buf,BUFFER_SIZE,0,(struct sockaddr*)&client_device[i].sockaddr_udp1,&len);
if (byte_num < 0)
{
   printf("udp接收错误\n");
   perror("recvfrom");
}

printf("5G装置udp2:%s端口号:%d\n", udp2_buf,ntohs(client_device[i].sockaddr_udp1.sin_port)); 
if(sendto(sockfd_udp2,udp2_buf,byte_num,0,(struct sockaddr*)&client_device[i].sockaddr_udp1,len) == -1)
{ 
   printf("udp发送错误\n");
   perror("sendto");
}
  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值