Xamarin Forms如何更改套接字连接的端口或IP地址
Xamarin Forms How to change Port or IPAddress of socket connection
我有一个 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;
}
}
所以我找不到任何快速答案,所以不得不自己想办法。如果您发现其中有任何问题,请告诉我。
首先我声明了一个e_Num如下
public enum ge_SocketStatus
{
e_NotListening = 0,
e_Listening = 1,
e_Restart = 2
}
然后我向我的 class 添加了一个 StopListening 函数来处理我所有的套接字通信并将套接字状态设置为不监听,如下所示:
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 循环退出后最后一次调用此函数。此时套接字未连接,因此尝试使用 is 执行任何操作(例如 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 函数结束并且来自套接字的所有内容都断开连接,我可以再次调用开始侦听并在不同的 IP 地址和/或端口上打开套接字。
希望这对我有所帮助,因为我找不到好的解决方案。
我有一个 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;
}
}
所以我找不到任何快速答案,所以不得不自己想办法。如果您发现其中有任何问题,请告诉我。
首先我声明了一个e_Num如下
public enum ge_SocketStatus
{
e_NotListening = 0,
e_Listening = 1,
e_Restart = 2
}
然后我向我的 class 添加了一个 StopListening 函数来处理我所有的套接字通信并将套接字状态设置为不监听,如下所示:
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 循环退出后最后一次调用此函数。此时套接字未连接,因此尝试使用 is 执行任何操作(例如 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 函数结束并且来自套接字的所有内容都断开连接,我可以再次调用开始侦听并在不同的 IP 地址和/或端口上打开套接字。
希望这对我有所帮助,因为我找不到好的解决方案。