Tom*_*Tom 12 .net c# sockets windows-services tcp
我有一个在.net 4.0中使用异步服务器套接字开发的TCP服务器Windows服务.
它工作,但大约90%的时间我根本无法阻止它:在Windows服务控制台中按停止按钮后,它会在大约一分钟后挂起并停止,但其过程继续,TCP通信继续.它挂在_listener.Close().我只能重新启动Windows才能关闭通信.关闭套接字可能有些东西.我试图搞清楚,但我根本找不到问题的根源.
客户端不在我的控制之下,它们是通过TCP发送数据的大约100个小工具.
这是我的代码(更新).
非常感谢,任何建议都非常感谢!
public class DeviceTCPServer
{
public readonly IPAddress IPAddress;
public readonly int Port;
public readonly int InputBufferSize;
public readonly ConcurrentDictionary<Guid, StateObject> Connections;
public event EventHandler OnStarted;
public event EventHandler OnStopped;
public event ServerEventHandler OnConnected;
public event ServerEventHandler OnDisconnected;
public event RecievedEventHandler OnRecieved;
public event DroppedEventHandler OnDropped;
public event ExceptionEventHandler OnException;
public event ServerLogEventHandler ServerLog;
private volatile bool _iAmListening;
private Socket _listener;
private Thread _listenerThread;
private readonly ManualResetEvent _allDone = new ManualResetEvent(false);
public bool Listening
{
get { return _iAmListening; }
}
public DeviceTCPServer(IPAddress ipAddress,
int port,
int inputBufferSize)
{
IPAddress = ipAddress;
Port = port;
InputBufferSize = inputBufferSize;
Connections = new ConcurrentDictionary<Guid, StateObject>();
}
public void ThreadedStart()
{
_listenerThread = new Thread(Start)
{
CurrentUICulture = Thread.CurrentThread.CurrentUICulture,
IsBackground = true
};
_listenerThread.Start();
}
private void Start()
{
try
{
var localEP = new IPEndPoint(IPAddress, Port);
_listener = new Socket(localEP.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
_listener.Bind(localEP);
_listener.Listen(10000);
if (OnStarted != null)
OnStarted(this, new EventArgs());
_iAmListening = true;
var listenerWithCultureInfo = new Tuple<Socket, CultureInfo>(_listener,
Thread.CurrentThread.CurrentUICulture);
while (_iAmListening)
{
_allDone.Reset();
_listener.BeginAccept(AcceptCallback, listenerWithCultureInfo);
_allDone.WaitOne();
}
}
catch (Exception exc)
{
Debug.Assert(false, exc.Message);
if (OnException != null)
OnException(this, new ExceptionEventArgs(exc, "Start"));
}
}
public void StopListening()
{
try
{
_iAmListening = false;
_allDone.Set();
}
catch(Exception exc)
{
Debug.Assert(false, exc.Message);
if (OnException != null)
OnException(this, new ExceptionEventArgs(exc, "StopListening"));
}
}
public void Stop()
{
try
{
_listener.Close(0);
CloseAllConnections();
_listenerThread.Abort();
}
catch (Exception exc)
{
Debug.Assert(false, exc.Message);
if (OnException != null)
OnException(this, new ExceptionEventArgs(exc, "Stop"));
}
}
private void AcceptCallback(IAsyncResult ar)
{
var arTuple = (Tuple<Socket, CultureInfo>)ar.AsyncState;
var state = new StateObject(arTuple.Item2, InputBufferSize);
try
{
Connections.AddOrUpdate(state.Guid,
state,
(k, v) => v);
Thread.CurrentThread.CurrentUICulture = state.CurrentUICulture;
var listener = arTuple.Item1;
var handler = listener.EndAccept(ar);
_allDone.Set();
if (!_iAmListening)
return;
state.WorkSocket = handler;
handler.BeginReceive(state.Buffer, 0, state.InputBufferSize, 0,
RecieveCallBack, state);
if (OnConnected != null)
OnConnected(this, new ServerEventArgs(state));
}
catch(ObjectDisposedException)
{
_allDone.Set();
return;
}
catch (Exception exc)
{
Debug.Assert(false, exc.Message);
if (OnException != null)
OnException(this, new ExceptionEventArgs(exc, state, "AcceptCallback"));
}
}
public void RecieveCallBack(IAsyncResult ar)
{
var state = (StateObject)ar.AsyncState;
try
{
Thread.CurrentThread.CurrentUICulture = state.CurrentUICulture;
var handler = state.WorkSocket;
var read = handler.EndReceive(ar);
var pBinayDataPocketCodecStore = new BinayDataPocketCodecStore();
if (read > 0)
{
state.LastDataReceive = DateTime.Now;
var data = new byte[read];
Array.Copy(state.Buffer, 0, data, 0, read);
state.AddBytesToInputDataCollector(data);
//check, if pocket is complete
var allData = state.InputDataCollector.ToArray();
var codecInitRes = pBinayDataPocketCodecStore.Check(allData);
if (codecInitRes.Generic.Complete)
{
if (!codecInitRes.Generic.Drop)
{
if (OnRecieved != null)
OnRecieved(this, new RecievedEventArgs(state, allData));
}
else
{
if (OnDropped != null)
OnDropped(this, new DroppedEventArgs(state, codecInitRes.Generic));
//get new data
state.ResetInputDataCollector();
handler.BeginReceive(state.Buffer, 0, state.InputBufferSize, 0,
RecieveCallBack, state);
}
}
else
{
//get more data
handler.BeginReceive(state.Buffer, 0, state.InputBufferSize, 0,
RecieveCallBack, state);
}
}
else
{
if ((handler.Connected == false) || (handler.Available == 0))
{
Close(state);
}
}
}
catch (Exception exc)
{
Debug.Assert(false, exc.Message);
if (OnException != null)
OnException(this, new ExceptionEventArgs(exc, state, "RecieveCallBack"));
}
}
public void Send(StateObject state, byte[] data)
{
try
{
var handler = state.WorkSocket;
handler.BeginSend(data, 0, data.Length, 0,
SendCallback, state);
}
catch (Exception exc)
{
Debug.Assert(false, exc.Message);
if (OnException != null)
OnException(this, new ExceptionEventArgs(exc, state, "Send"));
}
}
private void SendCallback(IAsyncResult ar)
{
var state = (StateObject)ar.AsyncState;
try
{
Thread.CurrentThread.CurrentUICulture = state.CurrentUICulture;
var handler = state.WorkSocket;
handler.EndSend(ar);
handler.BeginReceive(state.Buffer, 0, state.InputBufferSize, 0,
RecieveCallBack, state);
}
catch (Exception exc)
{
Debug.Assert(false, exc.Message);
if (OnException != null)
OnException(this, new ExceptionEventArgs(exc, state, "SendCallback"));
}
}
public void Close(StateObject state)
{
try
{
if (state == null)
return;
var handler = state.WorkSocket;
if (handler == null)
return;
if (!handler.Connected)
return;
if (handler.Available > 0)
{
var data = new byte[handler.Available];
handler.Receive(data);
}
handler.Shutdown(SocketShutdown.Both);
handler.Close(0);
if (OnDisconnected != null)
OnDisconnected(this, new ServerEventArgs(state));
StateObject removed;
var removeResult = Connections.TryRemove(state.Guid, out removed);
}
catch (Exception exc)
{
Debug.Assert(false, exc.Message);
if (OnException != null)
OnException(this, new ExceptionEventArgs(exc, "Close"));
}
}
private void CloseAllConnections()
{
try
{
var connections = Connections.Select(c => c.Value);
foreach(var connection in connections)
{
Close(connection);
}
}
catch(Exception exc)
{
Debug.Assert(false, exc.Message);
if (OnException != null)
OnException(this, new ExceptionEventArgs(exc, "CloseAllConnections"));
}
}
public override string ToString()
{
return string.Format("{0}:{1}", IPAddress, Port);
}
}
Run Code Online (Sandbox Code Playgroud)
所以,问题终于解决了,我的Windows服务没有任何问题!
\n\n这是由 Microsoft Windows 更新引起的:
\n\nMicrosoft KB4338815,导致 closesocket t\xd0\xbe 在 Intel Xeon 处理器上永远挂起: https://forum.filezilla-project.org/viewtopic.php ?t=49308
\n\n感谢您为帮助我所做的一切努力!
\n| 归档时间: |
|
| 查看次数: |
436 次 |
| 最近记录: |