Java DatagramChannel在Android上未接收任何字节
更新Java DatagramChannel在Android上未接收任何字节,java,android,networking,udp,selector,Java,Android,Networking,Udp,Selector,更新 我尝试了相同的实现,但这次使用了ServerSocketChannel/SocketChannel。这在安卓系统上有效。看起来我在安卓上的UDP上有100%的数据包丢失。有人对这件事的原因有想法吗?(这不是WiFi问题。UDP客户端在我的笔记本上工作。) 原创 我在Android应用程序中接收数据包时遇到问题。Android应用程序能够向桌面服务器发送数据,桌面服务器立即回复,但始终接收零字节。当我将其用作桌面客户端应用程序时,同样的代码也可以工作 我的Android应用程序具有互联网权限
我尝试了相同的实现,但这次使用了ServerSocketChannel/SocketChannel。这在安卓系统上有效。看起来我在安卓上的UDP上有100%的数据包丢失。有人对这件事的原因有想法吗?(这不是WiFi问题。UDP客户端在我的笔记本上工作。) 原创
我在Android应用程序中接收数据包时遇到问题。Android应用程序能够向桌面服务器发送数据,桌面服务器立即回复,但始终接收零字节。当我将其用作桌面客户端应用程序时,同样的代码也可以工作 我的Android应用程序具有互联网权限。我还尝试了网络,改变无线多播状态,接入无线状态和接入网络状态。可悲的是,这没有什么区别 在设备和模拟器上都进行了尝试 下面是代码和输出示例 主要活动:
private Thread thread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
thread = new Thread(new Client());
thread.start();
}
客户:
public class Client implements Runnable {
private static final String LOG_TAG = "NET";
private static final String IP = "--.---.---.--";
private static final int PORT = 6543;
private final ByteBuffer byteBuffer = ByteBuffer.allocate(256);
private boolean running;
public Client() {
running = false;
}
@Override
public void run() {
try {
final Selector selector = Selector.open();
final DatagramChannel datagramChannel = DatagramChannel.open();
datagramChannel.configureBlocking(false);
datagramChannel.register(selector, SelectionKey.OP_WRITE);
datagramChannel.connect(new InetSocketAddress(IP, PORT));
running = true;
while (running) {
selector.select();
final Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
final SelectionKey key = keys.next();
if (key.isReadable()) {
handleRead(key);
}
if (key.isValid() && key.isWritable()) {
handleWrite(key);
}
keys.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void handleRead(final SelectionKey key) throws IOException {
final DatagramChannel channel = (DatagramChannel) key.channel();
byteBuffer.clear();
final SocketAddress from = channel.receive(byteBuffer);
byteBuffer.flip();
Log.i(LOG_TAG, String.format("Received %d bytes from %s", byteBuffer.limit(), from));
key.interestOps(SelectionKey.OP_WRITE);
}
private void handleWrite(final SelectionKey key) throws IOException {
final DatagramChannel channel = (DatagramChannel) key.channel();
byteBuffer.clear();
byteBuffer.putInt(1234);
byteBuffer.flip();
final SocketAddress to = new InetSocketAddress(IP, PORT);
final int bytes = channel.send(byteBuffer, to);
Log.i(LOG_TAG, String.format("Send %d bytes to %s", bytes, to));
key.interestOps(SelectionKey.OP_READ);
}
}
公共类客户端实现可运行{
私有静态最终字符串LOG_TAG=“NET”;
私有静态最终字符串IP=“-->”;
专用静态最终int端口=6543;
私有最终ByteBuffer ByteBuffer=ByteBuffer.allocate(256);
私有布尔运行;
公共客户机(){
运行=错误;
}
@凌驾
公开募捐{
试一试{
最终选择器=Selector.open();
final DatagramChannel DatagramChannel=DatagramChannel.open();
datagramChannel.configureBlocking(假);
datagramChannel.register(选择器、SelectionKey.OP_写入);
连接(新的InetSocketAddress(IP,端口));
运行=真;
(跑步时){
selector.select();
final Iterator keys=selector.selectedKeys().Iterator();
while(keys.hasNext()){
最终选择键=键。下一步();
if(key.isReadable()){
把手(钥匙);
}
if(key.isValid()&&key.isWritable()){
handleWrite(键);
}
键。移除();
}
}
}捕获(IOE异常){
e、 printStackTrace();
}
}
private void HandlerRead(最终选择密钥密钥)引发IOException{
final DatagramChannel=(DatagramChannel)key.channel();
byteBuffer.clear();
最终SocketAddress from=通道.receive(byteBuffer);
byteBuffer.flip();
Log.i(Log_标记,String.format(“从%s接收%d字节”,byteBuffer.limit(),from));
key.interesttops(选择key.OP_WRITE);
}
private void handleWrite(最终选择密钥)引发IOException{
final DatagramChannel=(DatagramChannel)key.channel();
byteBuffer.clear();
byteBuffer.putInt(1234);
byteBuffer.flip();
最终SocketAddress to=新的InetSocketAddress(IP,端口);
final int bytes=channel.send(byteBuffer,to);
Log.i(Log_标记,String.format(“发送%d字节到%s”,字节到));
key.interesttops(选择key.OP_READ);
}
}
服务器:
public class Server implements Runnable {
private static final int PORT = 6543;
private final ByteBuffer byteBuffer = ByteBuffer.allocate(256);
private SocketAddress from;
private boolean running;
public Server() {
from = null;
running = false;
}
@Override
public void run() {
try {
final Selector selector = Selector.open();
final DatagramChannel datagramChannel = DatagramChannel.open();
datagramChannel.configureBlocking(false);
datagramChannel.socket().setReuseAddress(true);
datagramChannel.register(selector, SelectionKey.OP_READ);
datagramChannel.bind(new InetSocketAddress(PORT));
running = true;
while (running) {
selector.selectNow();
final Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
final SelectionKey key = keys.next();
if (key.isReadable()) {
handleRead(key);
}
if (key.isValid() && key.isWritable()) {
handleWrite(key);
}
keys.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void handleRead(final SelectionKey key) throws IOException {
final DatagramChannel channel = (DatagramChannel) key.channel();
byteBuffer.clear();
from = channel.receive(byteBuffer);
byteBuffer.flip();
System.out.println(String.format("Received %d bytes from %s", byteBuffer.limit(), from));
key.interestOps(SelectionKey.OP_WRITE);
}
private void handleWrite(final SelectionKey key) throws IOException {
final DatagramChannel channel = (DatagramChannel) key.channel();
if (from != null) {
byteBuffer.clear();
byteBuffer.putInt(1234);
byteBuffer.flip();
final int bytes = channel.send(byteBuffer, from);
System.out.println(String.format("Send %d bytes to %s", bytes, from));
}
key.interestOps(SelectionKey.OP_READ);
}
public static void main(String args[]) {
new Thread(new Server()).start();
}
}
公共类服务器实现可运行{
专用静态最终int端口=6543;
私有最终ByteBuffer ByteBuffer=ByteBuffer.allocate(256);
来自的私有SocketAddress;
私有布尔运行;
公共服务器(){
from=null;
运行=错误;
}
@凌驾
公开募捐{
试一试{
最终选择器=Selector.open();
final DatagramChannel DatagramChannel=DatagramChannel.open();
datagramChannel.configureBlocking(假);
datagramChannel.socket().setReuseAddress(true);
datagramChannel.register(选择器,SelectionKey.OP_READ);
bind(新的InetSocketAddress(端口));
运行=真;
(跑步时){
selector.selectNow();
final Iterator keys=selector.selectedKeys().Iterator();
while(keys.hasNext()){
最终选择键=键。下一步();
if(key.isReadable()){
把手(钥匙);
}
if(key.isValid()&&key.isWritable()){
handleWrite(键);
}
键。移除();
}
}
}捕获(IOE异常){
e、 printStackTrace();
}
}
private void HandlerRead(最终选择密钥密钥)引发IOException{
final DatagramChannel=(DatagramChannel)key.channel();
byteBuffer.clear();
from=信道接收(byteBuffer);
byteBuffer.flip();
System.out.println(String.format(“从%s接收%d字节”,byteBuffer.limit(),from));
key.interesttops(选择key.OP_WRITE);
}
private void handleWrite(最终选择密钥)引发IOException{
final DatagramChannel=(DatagramChannel)key.channel();
if(from!=null){
byteBuffer.clear();
byteBuffer.putInt(1234);
byteBuffer.flip();
final int bytes=channel.send(byteBuffer,from);
System.out.println(String.format(“发送%d字节到%s”,字节,从));
}
key.interesttops(选择key.OP_READ);
}
公共静态void main(字符串参数[]){
新线程(新服务器()).start();
}
}
客户端输出:
将4个字节发送到/——:6543从null接收到0字节
将4个字节发送到/——:6543
从null接收到0字节
服务器输出: 从/-:52974接收到4个字节
将4个字节发送到/——:52974
从/-:52974接收到4个字节
将4个字节发送到/——:52974
当您不调用bind()时,为什么要在客户端中调用setReuseAddress()?你为什么睡觉?为什么要调用connect()并在send()中指定目标地址?当相应的参数是整数时,为什么要指定%s?@EJP在从服务器代码复制演示代码后没有删除它。只是睡觉,这样我就不会被淹死