sockets - Xamarin Forms如何更改套接字连接的端口或IPAddress
问题描述
我有一个监听传入消息的 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
}
然后我在我的类中添加了一个 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 循环退出后最后一次调用了该函数。此时套接字未连接,因此尝试对 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 函数结束并且来自套接字的所有内容都断开连接,我可以再次调用开始监听并在不同的 IPAddress 和/或端口上打开套接字。
我希望这会有所帮助,因为我找不到一个好的解决方案。
推荐阅读
- javascript - 如何在 Apify web 中的 pageFunction 执行之间传递数据
- python - 为什么 Crontab 没有运行我的 python 脚本?
- alexa - 无法在 alexa 网络控制台中找到我的 alexa 技能的亚马逊支付许可
- python - 绘制直方图的峰值
- sql - 将 SELECT 子查询与别名和 FROM 一起使用
- html - 锚定到另一个页面到移动设备中的错误元素
- amazon-web-services - 当应用程序关闭时,根据来自 3rd 方 API 的数据向 React Native App 推送通知
- excel - 制作具有特定名称的新工作簿
- r - 如何在 data.table 中使用 cmd 删除坏行?
- python - 如何在每次迭代中返回循环和条件中的值?