Xamarin Forms如何更改套接字连接的端口或IP地址

问题描述 投票:0回答:1

我有一个UWP(也即将成为MacOS)应用程序,用于监听传入的消息。用户可以配置要监听的IP地址和端口。套接字连接侦听后,用户还可以返回设置并更改IP地址或端口。我试图弄清楚如何在用户更改值时关闭现有的侦听器并使用新的“端口/ IP地址”重新启动它。这是启动侦听器的代码。任何帮助,将不胜感激。

   private static Socket iobj_listener;

    public async static Task StartListening()
    {
        try
        {
            Debug.WriteLine("Point 1");
            IPEndPoint localEndPoint = new IPEndPoint(ViewModelObjects.AppSettings.ServerIPAddress, ViewModelObjects.AppSettings.ServerPort);

            // Create a TCP/IP socket.  
            iobj_listener = new Socket(ViewModelObjects.AppSettings.ServerIPAddress.AddressFamily,
                SocketType.Stream, ProtocolType.Tcp);

            // Bind the socket to the local endpoint and listen for incoming connections.  
            iobj_listener.Bind(localEndPoint);
            iobj_listener.Listen(100);
            ViewModelObjects.AppSettings.ListeningOnSocket = true;

            while (true)
            {
                Debug.WriteLine("Point 2");
                // Set the event to nonsignaled state.  
                allDone.Reset();

                // Start an asynchronous socket to listen for connections.  
                Debug.WriteLine("Waiting for a connection on " + ViewModelObjects.AppSettings.ServerIPAddress.ToString() + "...");
                iobj_listener.BeginAccept(
                    new AsyncCallback(AcceptCallback),
                    iobj_listener);

                // Wait until a connection is made before continuing.  
                allDone.WaitOne();
            }

        }
        catch (Exception e)
        {
            Debug.WriteLine(e.ToString());
        }
        finally
        {
            Debug.WriteLine("Point 3");
            ViewModelObjects.AppSettings.ListeningOnSocket = false;
        }
    }
sockets xamarin.forms xamarin.uwp
1个回答
0
投票

所以我找不到任何快速答案,因此必须自己解决这个问题。如果您对此有任何疑问,请告诉我。

首先,我声明了一个e_Num如下

public enum ge_SocketStatus
{
    e_NotListening = 0,
    e_Listening = 1,
    e_Restart = 2
}

然后,我在类中添加了一个StopListening函数,该函数处理我所有的Socket通信,并将套接字状态设置为不监听,如下所示:

    public static async Task StopListening()
    {
        try
        {
            if (iobj_listener.Connected)
            {
                //Wait till the connection ends or 30 seconds - this is so any last messages can be processed.
                await Task.Delay(30000);

            }
            ViewModelObjects.AppSettings.SocketStatus = ge_SocketStatus.e_NotListening;
            iobj_listener.Close(1);

        }
        catch (Exception ex)
        {
            App.AppException(ex);
        }
    }

然后我使用该枚举的值来知道何时结束循环:

 public async static Task StartListening()
    {
        try
        {
            Debug.WriteLine("Point 1");
            IPEndPoint localEndPoint = new     IPEndPoint(ViewModelObjects.AppSettings.ServerIPAddress, ViewModelObjects.AppSettings.ServerPort);

            // Create a TCP/IP socket.  
            iobj_listener = new Socket(ViewModelObjects.AppSettings.ServerIPAddress.AddressFamily,
                SocketType.Stream, ProtocolType.Tcp);

            // Bind the socket to the local endpoint and listen for incoming connections.  
            iobj_listener.Bind(localEndPoint);
            iobj_listener.Listen(100);
            ViewModelObjects.AppSettings.SocketStatus = ge_SocketStatus.e_Listening;


            while (ViewModelObjects.AppSettings.SocketStatus == ge_SocketStatus.e_Listening)
            {
                Debug.WriteLine("Point 2");
                // Set the event to nonsignaled state.  
                allDone.Reset();

                // Start an asynchronous socket to listen for connections.  
                Debug.WriteLine("Waiting for a connection on " + ViewModelObjects.AppSettings.ServerIPAddress.ToString() + "...");
                iobj_listener.BeginAccept(
                    new AsyncCallback(AcceptCallback),
                    iobj_listener);

                // Wait until a connection is made before continuing.  
                allDone.WaitOne();
            }

        }
        catch (Exception e)
        {
            Debug.WriteLine(e.ToString());
        }
        finally
        {
            Debug.WriteLine("Point 3");
        }
    }

此行上方

while (ViewModelObjects.AppSettings.SocketStatus == ge_SocketStatus.e_Listening)

曾经是

while (true)

所以循环永远不会结束。

我发现一个陷阱是在套接字的BeginAccept函数中使用的AcceptCallback中。在此代码中,我还必须检测套接字是否已连接,因为该函数在StartListening循环退出后最后一次被调用。此时套接字未连接,因此尝试使用诸如EndAccept之类的任何东西都会导致应用程序引发异常。在下面,您可以看到我添加行的位置

if (listener.Connected)

为了防止代码在我关闭连接后崩溃。

   public static void AcceptCallback(IAsyncResult ar)
    {
        // Signal the main thread to continue.  
        allDone.Set();

        // Get the socket that handles the client request.  
        Socket listener = (Socket)ar.AsyncState;


        //If we have shut down the socket don't do this.  
        if (listener.Connected)
        {
            Socket handler = listener.EndAccept(ar);

            // Create the state object.  
            StateObject state = new StateObject();
            state.workSocket = handler;
            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReadCallback), state);
        }
    }

一旦所有StopListening函数结束并且套接字上的所有连接都断开,我可以再次调用start listen并在其他IPAddress和或Port上打开套接字。

我希望这会有所帮助,因为我找不到很好的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.