具有Win10 IoT的Raspberry Pi与Xamarin Android应用程序之间的TCP通信

时间:2018-07-25 08:43:49

标签: c# xamarin.android raspberry-pi3 windows-10-iot-core

我正在尝试在具有Win 10 IoT的Raspberry Pi 3和由Xamarin Android开发的App之间开发一个简单的TCP服务器/客户端。 我正在使用我的Samsung S9 +调试应用程序。 服务器是Raspberry。

在Raspberry中,我输入了以下代码:

protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        this.StartServer();
    }

    private async void StartServer()
    {
        try
        {
            //Create a StreamSocketListener to start 
            //listening for TCP connections.
            Windows.Networking.Sockets.StreamSocketListener socketListener = new Windows.Networking.Sockets.StreamSocketListener();

            //Hook up an event handler to call when connections are received.
            socketListener.ConnectionReceived += SocketListener_ConnectionReceived;

            //Start listening for incoming TCP connections on the specified port. You can specify any port that's not currently in use.
            await socketListener.BindEndpointAsync(new Windows.Networking.HostName("localhost"),"9999");

        }
        catch (Exception e)
        {
            Debug.WriteLine(e.Message);
        }
    }

    private async void socketListener_ConnectionReceived(Windows.Networking.Sockets.StreamSocketListener sender, Windows.Networking.Sockets.StreamSocketListenerConnectionReceivedEventArgs args)
    {
        //Read line from the remote client.
        Stream inStream = args.Socket.InputStream.AsStreamForRead();
        StreamReader reader = new StreamReader(inStream);
        string request = await reader.ReadLineAsync();

        //Send the line back to the remote client.
        Stream outStream = args.Socket.OutputStream.AsStreamForWrite();
        StreamWriter writer = new StreamWriter(outStream);
        await writer.WriteLineAsync(request);
        await writer.FlushAsync();
    }

在Xamarin App中,我有这个:

public class MainActivity : AppCompatActivity
{

    EditText txtInvia;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        // Set our view from the "main" layout resource
        SetContentView(Resource.Layout.activity_main);
        Button btnInvia = FindViewById<Button>(Resource.Id.btnInvia);
        Button btnConnetti = FindViewById<Button>(Resource.Id.btnConnetti);
        txtInvia = FindViewById<EditText>(Resource.Id.txtInvia);

        btnConnetti.Click += BtnConnetti_Click;
        btnInvia.Click += BtnInvia_Click;
    }

    private void BtnInvia_Click(object sender, EventArgs e)
    {
    }

    private void BtnConnetti_Click(object sender, EventArgs e)
    {
        this.StartClient();
    }

    public static bool PING(string ipAddress)
    {
        // Ping's the local machine.
        Ping pingSender = new Ping();
        IPAddress address = IPAddress.Parse(ipAddress);
        PingReply reply = pingSender.Send(address);

        if (reply.Status == IPStatus.Success)
        {
            Console.WriteLine("Address: {0}", reply.Address.ToString());
            Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
            Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
            Console.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
            Console.WriteLine("Buffer size: {0}", reply.Buffer.Length);
            return true;
        }
        else
        {
            Console.WriteLine(reply.Status);
            return false;
        }
    }

    private const int PortNumber = 9999;
    private void StartClient()
    {
        string localAddr = "192.168.137.1";
        if (PING(localAddr))
        {
            try
            {
                MyClientTask myClientTask = new MyClientTask(localAddr, PortNumber, string.Format(txtInvia.Text + "\r\n"));
                myClientTask.Execute();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

        }
    }

}

MyClientTask在哪里:

public class MyClientTask : AsyncTask
{

    string dstAddress;
    int dstPort;
    string response = "";
    string msgToServer;

    public MyClientTask(string addr, int port, string msgTo)
    {
        dstAddress = addr;
        dstPort = port;
        msgToServer = msgTo;
    }

    protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] @params)
    {
        Socket socket = null;
        DataOutputStream dataOutputStream = null;

        try
        {
            socket = new Socket(dstAddress, dstPort);
            dataOutputStream = new DataOutputStream(socket.OutputStream);

            if (msgToServer != null)
            {
                dataOutputStream.WriteBytes(msgToServer);
            }
            ByteArrayOutputStream byteArrayOutputStream =
                    new ByteArrayOutputStream(1024);
            byte[] buffer = new byte[1024];

            int bytesRead;
            System.IO.Stream inputStream = socket.InputStream;

            /*
             * notice:
             * inputStream.read() will block if no data return
             */
            while ((bytesRead = inputStream.Read(buffer)) != -1)
            {
                byteArrayOutputStream.Write(buffer, 0, bytesRead);
                response += byteArrayOutputStream.ToString("UTF-8");
            }

        }
        catch (UnknownHostException e)
        {
            // TODO Auto-generated catch block
            e.PrintStackTrace();
            response = "UnknownHostException: " + e.ToString();
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.PrintStackTrace();
            response = "IOException: " + e.ToString();
        }
        finally
        {
            if (socket != null)
            {
                try
                {
                    socket.Close();
                }
                catch (IOException e)
                {
                    // TODO Auto-generated catch block
                    e.PrintStackTrace();
                }
            }
        }
        return null;
    }

}

在MyClientTask中,我使用以下指令创建新套接字:

socket = new Socket(dstAddress, dstPort);

如果我将手机连接到Raspberry创建的HotSpot,则会收到此错误

IOException: Java.Net.ConnectException: failed to connect to /192.168.137.175 (port 9999) from /:: (port 37604): connect failed: ECONNREFUSED (Connection refused) ---> Android.Systems.ErrnoException: connect failed: ECONNREFUSED (Connection refused)

如果我在同一路由器上通过以太网将手机连接到WiFi和Raspberry,则Xamarin App会因为超时而无法创建套接字。

我做错了什么? 谢谢! <3

编辑: 我发现应用程序中Raspberry的IP地址是错误的,所以现在是正确的,我的应用程序被阻止的方式与以太网连接相同。

1 个答案:

答案 0 :(得分:0)

首先,您可以使用 BindServiceNameAsync 方法而不是 BindEndpointAsync 方法,以将流量限制为地址或适配器。

第二,您需要为使用的服务器端口设置防火墙阻止,以下命令可以允许访问。

netsh advfirewall firewall add rule name="Tcp Server Port(9999)" dir=in protocol=TCP localport=9999 action=Allow

最后,您需要指定应用程序的device capabilities。应该为Tcp服务器启用Private Networks (Client & Server)功能。

您可以参考一个StreamSocket示例here。它显示了如何使用StreamSocketListener类创建TCP套接字以侦听传入的TCP连接。