- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在处理一些遗留的 TCP 服务器代码,这些代码直接与套接字一起使用,因为它是在 .NET 2.0 和更早版本中编写的。服务器具有“停止”和“开始”接受客户端连接的功能。
为了解决这个问题,我以管理员用户身份在控制台模式下运行服务器。最重要的是,我已经从等式中消除了套接字接受线程,所有代码所做的都是这样的:
tcpListener = new TcpListener(IPAddress.Any, this.Port);
tcpListener.Start();
和
tcpListener.Stop();
这是从不同的方法调用的。我调试了代码,我很确定代码只执行一次。但是,问题是调用 Stop
实际上并没有释放套接字地址,因此随后调用 Start
失败并出现错误“每个套接字地址只有一次使用(协议(protocol)/网络地址/端口)通常是允许的”。我还可以从 ProcessExplorer 确认服务器仍在监听服务器端口。
当我编写一个使用相同代码片段的小型控制台应用程序时,一切正常。我什至尝试过跟踪 .NET 网络和套接字库,但没有错误或任何表明那里存在问题的东西。
我不清楚为什么调用 Stop
没有释放套接字地址?
更新:经过更多调查后发现,子进程启动对 TcpListener
有一些奇怪的影响。我制作了一个“简单的”示例代码来说明这个问题:
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Threading;
namespace TcpListenerStartStop
{
class MyTcpListener
{
public static void Main(string[] args)
{
Int32 port = 13000;
if (args.Length > 0) // indicates child process
{
Thread.Sleep(4000); // as a child do nothing and wait for a few seconds
}
else // parent will play with the TcpListener
{
//LaunchChildProcess(); // launch child here and listener restart is fine?!?
var tcpListener = new TcpListener(IPAddress.Any, port);
tcpListener.Start();
Console.WriteLine("Starting test in 2 seconds...");
Thread.Sleep(2000);
LaunchChildProcess(); // launch child here and listener restart is not fine?!?
tcpListener.Stop();
Console.WriteLine("Stopped.");
Thread.Sleep(1000);
tcpListener.Start();
Console.WriteLine("Started");
}
Console.WriteLine("All is good, no exceptions :)");
}
private static void LaunchChildProcess()
{
Process process = new Process();
var processStartInfo = new ProcessStartInfo
{
CreateNoWindow = true,
FileName = Assembly.GetExecutingAssembly().Location,
UseShellExecute = false, // comment out this line out listener restart is fine?!?
Arguments = "child"
};
process.StartInfo = processStartInfo;
process.Start();
}
}
}
正如您从代码中看到的,如果我在创建监听器之前启动子进程,一切都很好,如果我在监听器重启失败后启动子进程。这与子进程的 UseShellExecute = false
选项有关。
不确定这是 .NET 错误还是我不知道的某些特殊行为?
最佳答案
此行为的真正原因是 TcpListener
套接字句柄与许多其他句柄一起由子进程继承。可以找到关于该主题的一些讨论 here和 here .
一个明显的解决方案是在初始化 TcpListener
之前启动子进程。
另一种解决方案是让 UseShellExecute = true
来避免此套接字句柄继承。
理想的解决方案是设置套接字句柄选项以防止子进程继承。可以通过 TcpListener 套接字句柄上的 P/Invoke 在 .NET 中执行此操作:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetHandleInformation(IntPtr hObject, uint dwMask, uint dwFlags);
private const uint HANDLE_FLAG_INHERIT = 1;
private static void MakeNotInheritable(TcpListener tcpListener)
{
var handle = tcpListener.Server.Handle;
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
}
关于c# - .NET TcpListener Stop 方法在有子进程时不会停止监听器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35280597/
我有一些代码: protected TcpListener ClientListener; protected TcpClient ClientSocket; protecte
我创建了一个新表单,并在顶部做了: using System; using System.Collections.Generic; using System.ComponentModel; using
我们目前在 Windows 上运行的自行编写的服务器应用程序遇到问题(出现在不同版本上)。服务器监听 TCP 端口,接受连接,交换一些数据,然后再次关闭连接。大约有 100 个客户端不时连接。 有时服
我正在玩一个用 F# 编写的简单网络服务器。正如我所注意到的,如果我在 Firefox 中点击刷新,经过一些尝试,我会收到一个错误页面: The connection was reset The co
为了这个问题的目的,我做了一个 super 简化的例子: using System; using System.Net; using System.Net.Sockets; namespace Loo
我有一个连接到多个客户端的 TcpListener。我可以获得所有已连接客户端的列表吗? 最佳答案 当您在服务器上接受连接时,您可以将客户端放在一个列表中。 TcpListener server =
以下代码与 TcpListener 的 Rust 文档中的代码几乎相同。当代码在 Ubuntu 14.04 上运行时,它不会产生任何错误,但同时它也不起作用! (netstat -an | grep
我有一个 TcpListener,它在关闭时会导致所有进行中的客户端在尝试调用 EndAcceptTcpClient 时抛出以下异常。是否可以使用更优雅的模式来允许所有现有客户端连接在 TcpList
我在 Windows 窗体应用程序中使用 TcpListener;它有一个启动 TcpListener 的“开始”按钮。但是,当我单击开始按钮时,会抛出以下异常: The requested addr
我的窗口上有两个 Button 连接到两个 ICommands: public ICommand Start { get; set; } public ICommand Stop { get; set
我在使用 TCPListener 时遇到问题。我在下面创建了这段代码,它可以与测试应用程序一起使用,但我无法让它接收来自生产环境的连接。在下图中,您可以看到 .44 不断尝试连接,但如控制台窗口输出所
大家好:我正在尝试确保我的 TcpListener 可以正确处理来自客户端的多个请求。我正在尝试在 for 循环内调用多个 BeginSend 方法,发现 Listener 的输出在我得到的响应数量方
我关注了this tutorial设置客户端 -> 服务器基于 TCP 的 Windows 窗体应用程序,其中服务器从客户端接收文件 并且运行良好。结构总结如下: Server uses TcpLis
我有一个通过 tcpListener 进行通信的服务。问题是当用户重新启动服务时 - 抛出“地址已在使用”异常,并且服务在几分钟左右无法启动。 有什么方法可以告诉系统终止旧连接以便我可以打开一个新连接
我如何检测客户端何时与 TcpListener 断开连接? 我的每个客户都在一个单独的线程中处理。 最佳答案 看NetworkStream.Read ,或者取决于您在代码中使用的内容可能是 TCPCl
据我了解,TcpListener一旦您调用Start(),将对连接进行排队.每次调用AcceptTcpClient (或 BeginAcceptTcpClient ),它将从队列中取出一项。 如果我们
你好我想问一下使用这个有什么区别: public TcpListener Listener; public TcpClient Client; Listener = new TcpListener(D
我有一个基于 TCPListener 的 ECHO 服务器应用程序.它接受客户端,读取数据,并返回相同的数据。我使用 async/await 方法开发了它,使用 XXXAsync框架提供的方法。 我已
抱歉发了这么长的帖子。我想使用 TcpListener 来监听端口,处理不同(后台)线程中传入连接请求的繁重工作,然后在准备就绪时将响应发送回客户端。我在MSDN上阅读了大量的代码和示例,并为服务器提
我有以下代码的实例,可以在Debug中或作为独立的Windows应用程序正确执行: TcpListener tcpListener = new TcpListener(IPAddress.Any, 4
我是一名优秀的程序员,十分优秀!