【发布时间】:2015-04-18 13:01:53
【问题描述】:
我正在使用多线程 system.net.socket 来监听单个端口。我想捕获来自多个客户端的同时请求。这是我的示例:
private static ManualResetEvent _manualResetEvent = new ManualResetEvent(false);
public class Program
{
static void Main(string[] args)
{
Program program = new Program();
Thread threadListener = new Thread(program.StartListening);
threadListener.Start();
}
private void StartListening()
{
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, Convert.ToInt32(ConfigurationManager.AppSettings["httpPort"].ToString()));
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Blocking = false;
listener.Bind(localEndPoint);
listener.Listen(10);
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
}
public static void AcceptCallback(IAsyncResult ar)
{
_manualResetEvent.Set();
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
}
private void ReceiveCallback(IAsyncResult result)
{
StateObject state = null;
Socket handler = null;
try
{
state = (StateObject)result.AsyncState;
handler = state.workSocket;
int numBytesReceived = handler.EndReceive(result);
if (!handler.Connected)
{
handler.Close();
return;
}
if (numBytesReceived > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, numBytesReceived));
string[] lines = state.sb.ToString().Split('\n');
if (lines[lines.Length-1] == "EOF")
{
// Do something according to client request
}
else
{
// We didn't receive all data. Continue receiving...
handler.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
}
}
}
catch (ObjectDisposedException ex)
{
// Don't care
}
catch (Exception ex)
{
if (handler != null)
{
handler.Close();
}
}
}
}
public class StateObject
{
public Socket workSocket = null;
public const int BufferSize = 256;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
}
问题是我无法仅使用这些代码来保持应用程序运行。如果我运行此应用程序并捕获客户端请求,我的 ReceiveCallBack 方法将正常工作,并且应用程序在成功执行后停止。
我可以使用这个MSDN link 中的示例代码来保持我的应用程序存活。它在 StartListening 方法中使用了一个 while 循环,如下所示:
while (true)
{
allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
allDone.WaitOne();
}
但似乎 MSDN 为阻塞侦听器设计了此代码。我的意思是它不允许同时连接。所以不适合我。
在 MSDN 示例中,如果没有 while 循环,我必须防止我的应用程序在执行我的代码后停止。我必须保持它运行并持续监听多个同时连接。
那么我怎样才能保持该应用程序运行呢?
谢谢
【问题讨论】:
-
您看到了什么异常消息?发布它和堆栈跟踪。
-
@Yuval 感谢您的关注,看来我今天用错误的词来定义我的问题。我会在 30 分钟后回来。你可以看到我编辑的问题。谢谢。
-
@OrkunBekar 我在您发布的代码中没有看到任何会停止应用程序的内容。这段代码将永远接受客户,所以问题不在于那部分。如果应用程序因其他原因停止,则需要查看该代码。并且 MSDN 代码不是为阻塞侦听器设计的,它允许任意数量的连接。它只接受第一个,然后你再次
BeginAccept。 -
@OrkunBekar 在这种情况下,您甚至根本不需要异步。您可以在循环中接受,然后调用 BeginReceive 以从那时起异步处理它。
-
@OrkunBekar 您接受连接,将接收设置为异步,接受另一个,异步接收等等。然后,您将同时处理所有连接。无论如何,您不能同时处理接受连接,它们总是顺序的。这是关于将异步并同时运行的实际数据传输。
标签: c# .net multithreading sockets