安卓编程,用udp方式发送数据这段代码中udp sendto 返回值(p)发送的这个函数总是出错,是哪里的问题呢 ?

一、有的手机不能直接接收UDP包,可能是手机厂商在定制Rom的时候把这个功能给关掉了。
1、可先在oncreate()方法里面实例化一个WifiManager.MulticastLock 对象lock;具体如下:
WifiManager manager = (WifiManager) this
.getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock lock= manager.createMulticastLock("test wifi");
2、在调用广播发送、接收报文之前先调用lock.acquire()方法;
3、用完之后及时调用lock.release()释放资源,否决多次调用lock.acquire()方法,程序可能会崩,详情请见
注;记得在配置文件里面添加如下权限:
&uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" /&
经过这样处理后,多数手机都能正常发送接收到广播报文。
本小点转载自
二、在UDP通信中,android端发送UDP广播包没有问题。至于接收的话,有时候不能接收到包。
在UDP通信中,android端发送UDP广播包没有问题。至于接收的话,有时候不能接收到包。但是如果UDP包中指定了目标主机的地址的话,那么android端就能正常接收。
下面上一段代码,大家可用这段代码进行测试。
1、在一个Service里面,我们创建一个线程
public void onCreate() {//用于创建线程
WifiManager manager = (WifiManager) this
.getSystemService(Context.WIFI_SERVICE);
udphelper = new UdpHelper(manager);
//传递WifiManager对象,以便在UDPHelper类里面使用MulticastLock
udphelper.addObserver(MsgReceiveService.this);
tReceived = new Thread(udphelper);
tReceived.start();
super.onCreate();
2、弄一个UDP帮助类,这个类主要用于发送和接收数据
package .ihome.bang.
import java.io.IOE
import java.net.DatagramP
import java.net.DatagramS
import java.net.InetA
import java.net.MulticastS
import java.net.SocketE
import java.net.UnknownHostE
import java.util.O
import .ihome.bang.tool.SendT
import android.net.wifi.WifiM
import android.util.L
* UdpHelper帮助类
* @author 陈喆榕
public class UdpHelper
implements Runnable {
Boolean IsThreadDisable = false;//指示监听线程是否终止
private static WifiManager.MulticastL
InetAddress mInetA
public UdpHelper(WifiManager manager) {
this.lock= manager.createMulticastLock("UDPwifi");
public void StartListen()
// UDP服务器监听的端口
Integer port = 8903;
// 接收的字节大小,客户端发送的数据不能超过这个大小
byte[] message = new byte[100];
// 建立Socket连接
DatagramSocket datagramSocket = new DatagramSocket(port);
datagramSocket.setBroadcast(true);
DatagramPacket datagramPacket = new DatagramPacket(message,
message.length);
while (!IsThreadDisable) {
// 准备接收数据
Log.d("UDP Demo", "准备接受");
this.lock.acquire();
datagramSocket.receive(datagramPacket);
String strMsg=new String(datagramPacket.getData()).trim();
Log.d("UDP Demo", datagramPacket.getAddress()
.getHostAddress().toString()
+ ":" +strMsg );this.lock.release();
} catch (IOException e) {//IOException
e.printStackTrace();
} catch (SocketException e) {
e.printStackTrace();
public static void send(String message) {
message = (message == null ? "Hello IdeasAndroid!" : message);
int server_port = 8904;
Log.d("UDP Demo", "UDP发送数据:"+message);
DatagramSocket s = null;
s = new DatagramSocket();
} catch (SocketException e) {
e.printStackTrace();
InetAddress local = null;
local = InetAddress.getByName("255.255.255.255");
} catch (UnknownHostException e) {
e.printStackTrace();
int msg_length = message.length();
byte[] messageByte = message.getBytes();
DatagramPacket p = new DatagramPacket(messageByte, msg_length, local,
server_port);
s.send(p);
s.close();
} catch (IOException e) {
e.printStackTrace();
public void run() {
StartListen();
阅读(...) 评论()[socket编程]TCP和UDP发送数据包的大小问题
用UDP协议发送时,用sendto函数最大能发送数据的长度为:6=65507字节,其中20字节为IP包头长度,8字节为UDP包头长度。用sendto函数发送数据时,如果指的的数据长度大于该值,则函数会返回错误。
用TCP协议发送时,由于TCP是数据流协议,因此不存在包大小的限制(暂不考虑缓冲区的大小),这是指在
用send函数时,数据长度参数不受限制。而实际上,所指定的这段数据并不一定会一次性发送出去,如果这段数据比较长,可能会被分段发送,如果比较短,可能会等待和下一次数据一起发送。
我在测试的时候,发现长度一般会被切成16384(16K)或49152(48K),不知道这两个值有什么意义。
比如在send()中设定发送数据的长度为100000,在接收端用recv()函数接收时,接收到的数据长度如下表:
start recvLen: 16384 & &
&nu: 0 & &type:
normal recvLen: 16384 & &nu:
0 & &type: 0
normal recvLen: 67232 & &nu:
0 & &type: 0
-------------------
normal recvLen: 49152 & &nu:
1 & &type: 1
normal recvLen: 49152 & &nu:
0 & &type: 0
normal recvLen: 1696 & &nu:
- & &type:
-------------------
normal recvLen: 49152 & &nu:
2 & &type: 1
normal recvLen: 49152 & &nu:
0 & &type: 0
normal recvLen: 1696 & &nu:
- & &type:
-------------------
从表中可以看出每次发送的100000byte的数据被拆成了3段,这3段长度加起来正好是100000。
经过测试得出如果将send()函数参数中的数据长度设为16384(16K),每次用recv()接收到的长度也为16384,而大于或小于这个值,都会被拆分或合并。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。2011年 总版技术专家分年内排行榜第三2010年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第五
本帖子已过去太久远了,不再提供回复功能。Linux 网络编程——原始套接字实例:发送 UDP 数据包_Linux编程_Linux公社-Linux系统门户网站
你好,游客
Linux 网络编程——原始套接字实例:发送 UDP 数据包
来源:Linux社区&
作者:tennysonsky
以太网报文格式:
详细的说明,请看《MAC 头部报文分析》。
IP 报文格式:
详细的说明,请看《IP 数据报格式详解》。
UDP 报文格式:
详细的说明,请看《UDP 数据报格式详解》。
校验和函数:
/*******************************************************功能:&校验和函数参数:&buf: 需要校验数据的首地址&nword: 需要校验数据长度的一半返回值:&校验和*******************************************************/unsigned short checksum(unsigned short *buf, int nword){&&for(sum = 0; nword & 0; nword--)&{& sum += htons(*buf);& buf++;&}&sum = (sum&&16) + (sum&0xffff);&sum += (sum&&16);&return ~}
下通过原始套接字组一个 udp 数据包,给 PC 机的网络调试助手发送信息:
#include &stdio.h&#include &stdlib.h&#include &string.h&#include &net/if.h&& & //struct ifreq#include &sys/ioctl.h&& &//ioctl、SIOCGIFADDR#include &sys/socket.h&#include &netinet/ether.h&& //ETH_P_ALL#include &netpacket/packet.h&&//struct sockaddr_ll
unsigned short checksum(unsigned short *buf, int nword);//校验和函数int main(int argc, char *argv[]){&//1.创建通信用的原始套接字&int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));&&//2.根据各种协议首部格式构建发送数据报&unsigned char send_msg[1024] = {& //--------------组MAC--------14------& 0x74, 0x27, 0xea, 0xb5, 0xef, 0xd8, //dst_mac: 74-27-EA-B5-FF-D8& 0xc8, 0x9c, 0xdc, 0xb7, 0x0f, 0x19, //src_mac: c8:9c:dc:b7:0f:19& 0x08, 0x00,& & & & & & & & & & & & //类型:0x0800 IP协议& //--------------组IP---------20------& 0x45, 0x00, 0x00, 0x00,& & & & & & //版本号:4, 首部长度:20字节, TOS:0, --总长度--:& 0x00, 0x00, 0x00, 0x00,& & //16位标识、3位标志、13位片偏移都设置0& 0x80, 17,& 0x00, 0x00,& & //TTL:128、协议:UDP(17)、16位首部校验和& 10,& 221,& 20,& 11,& & //src_ip: 10.221.20.11& 10,& 221,& 20,& 10,& & //dst_ip: 10.221.20.10& //--------------组UDP--------8+78=86------& 0x1f, 0x90, 0x1f, 0x90,& & & & & & //src_port:0x1f90(8080), dst_port:0x1f90(8080)& 0x00, 0x00, 0x00, 0x00,& & & & & & & //#--16位UDP长度--30个字节、#16位校验和&};&&int len = sprintf(send_msg+42, "%s", "this is for the udp test");&if(len % 2 == 1)//判断len是否为奇数&{& len++;//如果是奇数,len就应该加1(因为UDP的数据部分如果不为偶数需要用0填补)&}&&*((unsigned short *)&send_msg[16]) = htons(20+8+len);//IP总长度 = 20 + 8 + len&*((unsigned short *)&send_msg[14+20+4]) = htons(8+len);//udp总长度 = 8 + len&//3.UDP伪头部&unsigned char pseudo_head[1024] = {& //------------UDP伪头部--------12--& 10,& 221,& 20,& 11,& & //src_ip: 10.221.20.11& 10,& 221,& 20,& 10,& & //dst_ip: 10.221.20.10& 0x00, 17,& 0x00, 0x00,& & & & & & &//0,17,#--16位UDP长度--20个字节&};&&*((unsigned short *)&pseudo_head[10]) = htons(8 + len);//为头部中的udp长度(和真实udp长度是同一个值)&//4.构建udp校验和需要的数据报 = udp伪头部 + udp数据报&memcpy(pseudo_head+12, send_msg+34, 8+len);//--计算udp校验和时需要加上伪头部--&//5.对IP首部进行校验&*((unsigned short *)&send_msg[24]) = htons(checksum((unsigned short *)(send_msg+14),20/2));&//6.--对UDP数据进行校验--&*((unsigned short *)&send_msg[40]) = htons(checksum((unsigned short *)pseudo_head,(12+8+len)/2));&&&//6.发送数据&struct sockaddr_& & &//原始套接字地址结构&& & &//网络接口地址&&strncpy(ethreq.ifr_name, "eth0", IFNAMSIZ);& &//指定网卡名称&if(-1 == ioctl(sock_raw_fd, SIOCGIFINDEX, &req))&//获取网络接口&{& perror("ioctl");& close(sock_raw_fd);& exit(-1);&}&&/*将网络接口赋值给原始套接字地址结构*/&bzero(&sll, sizeof(sll));&sll.sll_ifindex = ethreq.ifr_&len = sendto(sock_raw_fd, send_msg, 14+20+8+len, 0 , (struct sockaddr *)&sll, sizeof(sll));&if(len == -1)&{& perror("sendto");&}&return 0;}
unsigned short checksum(unsigned short *buf, int nword){&&for(sum = 0; nword & 0; nword--)&{& sum += htons(*buf);& buf++;&}&sum = (sum&&16) + (sum&0xffff);&sum += (sum&&16);&return ~}
运行结果如下:
源代码下载:
------------------------------------------分割线------------------------------------------
免费下载地址在
用户名与密码都是
具体下载目录在 /2015年资料/4月/13日/Linux 网络编程&&原始套接字实例:发送 UDP 数据包/
下载方法见
------------------------------------------分割线------------------------------------------
本文永久更新链接地址:&
相关资讯 & & &
& (12/20/:32)
& (10/10/:35)
& (01/29/:15)
& (10/10/:43)
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款

我要回帖

更多关于 linux udp sendto 的文章

 

随机推荐