11

我正在尝试使用 Android 将 UDP 数据包发送到我计算机上用 C# 编写的服务器。当我在手机上运行该应用程序时,我得到一个非法状态异常。我认为这可能与对主要活动执行网络操作有关,但我不确定如何解决该问题。这是我的客户:

public class MainActivity extends Activity {

WifiManager wifi;
InetAddress dev_ip;
final int serverPort = 31337;
Thread drawThread = new Thread(new drawer());

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //set up wifi and connection
    wifi = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
    WifiInfo info = wifi.getConnectionInfo();
    int ip = info.getIpAddress();        
    String ipaddr = (ip & 0xff) + "." + (ip >> 8 & 0xff) + "." + (ip >> 16 & 0xff) + "." + (ip >> 24 & 0xff);

    try {
        dev_ip = InetAddress.getByName(ipaddr);
    } catch (UnknownHostException e) {
        Toast.makeText(this, "host error", Toast.LENGTH_LONG).show();
    }

    if (!wifi.isWifiEnabled())
       wifi.setWifiEnabled(true);

    Toast.makeText(this, "IP: " + ipaddr, Toast.LENGTH_LONG).show();     
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

public void draw(View view) throws IOException, SocketException
{
    drawThread.start();
}

public class drawer implements Runnable {

    public void run() {

        //transmit data
        try {
            DatagramSocket socket = new DatagramSocket(serverPort, /*myip*/);
            String test_data = "It works!";
            byte btest[] = new byte[50];
            btest = test_data.getBytes();
            DatagramPacket p1 = new DatagramPacket(btest, btest.length, /*myip*/, serverPort);
            socket.send(p1);
            socket.close();
        }   
        catch (IOException e) {
        }
    }
}
}

日志猫:

07-27 00:10:17.155: D/CLIPBOARD(1711): Hide Clipboard dialog at Starting input: 

finished by someone else... !
07-27 00:10:18.020: W/System.err(1711): java.net.BindException: bind failed: EADDRNOTAVAIL (Cannot assign requested address)
07-27 00:10:18.020: W/System.err(1711):     at libcore.io.IoBridge.bind(IoBridge.java:89)
07-27 00:10:18.020: W/System.err(1711):     at java.net.PlainDatagramSocketImpl.bind(PlainDatagramSocketImpl.java:68)
07-27 00:10:18.020: W/System.err(1711):     at java.net.DatagramSocket.createSocket(DatagramSocket.java:133)
07-27 00:10:18.020: W/System.err(1711):     at java.net.DatagramSocket.<init>(DatagramSocket.java:95)
07-27 00:10:18.020: W/System.err(1711):     at com.ls.styloid.MainActivity$drawer.run(MainActivity.java:67)
07-27 00:10:18.025: W/System.err(1711):     at java.lang.Thread.run(Thread.java:856)
07-27 00:10:18.025: W/System.err(1711): Caused by: libcore.io.ErrnoException: bind failed: EADDRNOTAVAIL (Cannot assign requested address)
07-27 00:10:18.025: W/System.err(1711):     at libcore.io.Posix.bind(Native Method)
07-27 00:10:18.025: W/System.err(1711):     at libcore.io.ForwardingOs.bind(ForwardingOs.java:39)
07-27 00:10:18.025: W/System.err(1711):     at libcore.io.IoBridge.bind(IoBridge.java:87)
07-27 00:10:18.025: W/System.err(1711):     ... 5 more
07-27 00:10:42.090: D/CLIPBOARD(1711): Hide Clipboard dialog at Starting input: finished by someone else... !
07-27 00:11:30.150: W/System.err(2535): java.net.BindException: bind failed: EADDRNOTAVAIL (Cannot assign requested address)
07-27 00:11:30.155: W/System.err(2535):     at libcore.io.IoBridge.bind(IoBridge.java:89)
07-27 00:11:30.155: W/System.err(2535):     at java.net.PlainDatagramSocketImpl.bind(PlainDatagramSocketImpl.java:68)
07-27 00:11:30.155: W/System.err(2535):     at java.net.DatagramSocket.createSocket(DatagramSocket.java:133)
07-27 00:11:30.155: W/System.err(2535):     at java.net.DatagramSocket.<init>(DatagramSocket.java:95)
07-27 00:11:30.155: W/System.err(2535):     at com.ls.styloid.MainActivity$drawer.run(MainActivity.java:67)
07-27 00:11:30.155: W/System.err(2535):     at java.lang.Thread.run(Thread.java:856)
07-27 00:11:30.155: W/System.err(2535): Caused by: libcore.io.ErrnoException: bind failed: EADDRNOTAVAIL (Cannot assign requested address)
07-27 00:11:30.155: W/System.err(2535):     at libcore.io.Posix.bind(Native Method)
07-27 00:11:30.155: W/System.err(2535):     at libcore.io.ForwardingOs.bind(ForwardingOs.java:39)
07-27 00:11:30.155: W/System.err(2535):     at libcore.io.IoBridge.bind(IoBridge.java:87)
07-27 00:11:30.155: W/System.err(2535):     ... 5 more
07-27 00:11:36.515: D/CLIPBOARD(2535): Hide Clipboard dialog at Starting input: finished by someone else... !

编辑:服务器似乎有很多我以前没有注意到的问题。当我根据其中一个答案重写侦听器时,它们开始发生。我有时会收到 label3 的“无法访问已处理的对象”错误、套接字异常 0x80004005,但仍然没有收到数据包。但是,在检查套接字状态时,它似乎是可读的。我可能搞砸了线程,请帮我解决这个问题。服务器:

public partial class Form1 : Form
    {
        Socket listener;
        Thread udp_listener;

        public Form1()
        {
            InitializeComponent();

            //set up listener thread
            udp_listener = new Thread(listen);
            udp_listener.IsBackground = true;
            udp_listener.Start();
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);
            listener.Close();
            udp_listener.Join();
        }

        private void listen()
        {
            //set up UDP
            const int serverPort = 31337;
            bool terminate = false;
            IPHostEntry iphost = Dns.GetHostEntry(Dns.GetHostName());
            IPAddress ipaddr = iphost.AddressList[0];
            IPEndPoint endpoint = new IPEndPoint(ipaddr, serverPort);
            listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            label3.Text = ipaddr.ToString();

            try
            {
                do
                {
                    byte[] buffer = new byte[100];
                    listener.Receive(buffer);
                    label3.Text = "Connected";
                    label3.ForeColor = Color.Red;
                    label3.Text = Encoding.UTF8.GetString(buffer);
                }
                while (!terminate);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
            finally
            {
                listener.Close();
            }

            listener.Close();
        }
    }

编辑2:

我尝试在我的计算机上使用 C# 创建一个客户端。数据包已发送,但我的服务器没有收到任何内容。

EDIT3:服务器现在工作正常,但 android 应用程序拒绝运行。这是代码:

   package com.tests.contest;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;

public class MainActivity extends Activity {
      private Socket sock;
      private BufferedWriter out;
      private Thread thrd;

      @Override
      public void onResume() {
        super.onResume();
        thrd = new Thread(new Runnable() {
            public void run() {
              while (!Thread.interrupted()) {
                runOnUiThread(new Runnable() {
                  @Override
                  public void run() {
                      try {
                        sock = new Socket("THEIP", 31337);
                    } catch (UnknownHostException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    } catch (IOException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                      try {
                        out = new BufferedWriter(new OutputStreamWriter(sock
                              .getOutputStream()));
                        out.write("WORKS");
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                  }
                });
              }
            }
          });
          thrd.start();
      }

      @Override
      public void onPause() {
        super.onPause();
        if (thrd != null)
          thrd.interrupt();
        try {
          if (sock != null) {
            sock.getOutputStream().close();
            sock.getInputStream().close();
            sock.close();
          }
        } catch (IOException e) {}
        thrd = null;
      }

      /*private void sendText() {
        String text = "HI";
        try {
          out.write(text + "\n");
          out.flush();
        } catch (IOException e) {}
      }*/
    }

出现问题是因为我在主线程上运行网络操作,而我显然没有这样做。

4

2 回答 2

7

例外是告诉您确切的操作:Socket在单独的Thread. AsyncTask您也可以为此使用 an 。

不允许Sockets在主 UI 线程上的原因是它可能导致应用程序Application Not Responding从等待Socket.

编辑:http ://thinkandroid.wordpress.com/2010/03/27/incorporating-socket-programming-into-your-applications/

您可以直接跳到客户端示例,因为您已经有一个桌面服务器。

edit2:由于我碰巧也在为我的 Android 应用程序使用 C# 服务器,因此我的桌面应用程序是如何创建侦听器的Socket

IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 27015); //Port 27015
Socket listener = new Socket(AddressFamily.InterNetwork,
    SocketType.Stream, ProtocolType.Tcp); // Create a TCP/IP socket.

我几乎可以肯定问题出在您的服务器/网络上。发送简单 UDP 数据包的 Android 代码看起来是正确的。您可能还想尝试通过localhost127.0.0.1编写一个简单的 C# 客户端程序进行连接。

编辑3:

使用这个基本应用程序,您应该能够在输入正确的 IP 地址后连接到服务器。按下发送将向服务器发送一些字节。使用它来确保您的连接正常工作。我已经确认它对我有用。如果这可行,那么我将为您的服务器问题打开一个新的 SO 问题,否则您的网络配置有问题。

于 2012-07-26T19:50:47.147 回答
2

我认为问题来自 do while 循环,因为您试图在循环中修改 UI 组件( label3 ),顺便说一下,无限循环会导致terminate变量始终为 false。尝试让修改 UI(label3.*)的代码退出循环。

于 2012-07-29T03:11:36.210 回答