C# TcpListener.AcceptSocket生成InvalidOperationException

C# TcpListener.AcceptSocket生成InvalidOperationException,c#,wcf,tcpclient,tcplistener,C#,Wcf,Tcpclient,Tcplistener,我不熟悉TcpListener和sockets,但我有以下代码,它们有时在我的初始化器类中从我的Wcf项目的App_代码中正确执行,但第一次正确执行时有时会显示错误,然后正确执行其他没有模式的代码 此行代码中的错误停止: Socket soc = listener.AcceptSocket(); 然后显示这些传统信息: 附加信息:不在听力中。在调用此方法之前,先调用Start()方法 但正如您所看到的,我在listener.AcceptSocket()之前调用start方法 我怀疑这是为了尝试

我不熟悉
TcpListener
sockets
,但我有以下代码,它们有时在我的初始化器类中从我的Wcf项目的App_代码中正确执行,但第一次正确执行时有时会显示错误,然后正确执行其他没有模式的代码

此行代码中的错误停止:

Socket soc = listener.AcceptSocket();
然后显示这些传统信息:

附加信息:不在听力中。在调用此方法之前,先调用Start()方法

但正如您所看到的,我在listener.AcceptSocket()之前调用start方法

我怀疑这是为了尝试在WCF项目中启动init守护进程

public static void AppInitialize()
{
    // This will get called on startup
    new Initializer().StartListener();
}

static TcpListener listener;
const int LIMIT = 5; //5 concurrent clients
private void StartListener()
{
    List<int> puertos = new List<int>();

    puertos.Add(5494);
    puertos.Add(5495);
    puertos.Add(5496);
    puertos.Add(5497);

    foreach (int puerto in puertos)
    {
        IPAddress localAddr = IPAddress.Parse(ConfigurationManager.AppSettings["ServerIP"]);
        listener = new TcpListener(localAddr, puerto);
        listener.Start();

        for (int i = 0; i < LIMIT; i++)
        {
            Thread t = new Thread(new ThreadStart(Service));
            t.Start();
        }
    }

}

private void Service()
{
    while (true)
    {
        //Error happen hear, but listener.Start execute before... .
        Socket soc = listener.AcceptSocket();

        try
        {

            byte[] resp = new byte[2000];
            var memStream = new MemoryStream();
            var bytes = 0;

            NetworkStream s = new NetworkStream(soc);
            StreamReader sr = new StreamReader(s);

            while (true)
            {
                string trama = "";
                if (s.CanRead)
                {
                    do
                    {
                        bytes = s.Read(resp, 0, resp.Length);
                        trama = Util.Util.ByteArrayToHexString(resp);
                    }
                    while (s.DataAvailable);
                }

                if (trama == "" || trama == null) break;

            }
            s.Close();
        }
        catch (Exception e)
        {
        }
        finally
        {
            soc.Close();
        }
    }

}
publicstaticvoidappinitialize()
{
//这将在启动时调用
新初始值设定项().StartListener();
}
静态TcpListener侦听器;
常数int极限=5//5个并发客户端
私用
{
List puertos=新列表();
普埃尔托斯增补本(5494);
普埃尔托斯增补本(5495);
普埃尔托斯增补本(5496);
普埃尔托斯增补本(5497);
foreach(普埃尔托斯港内)
{
IPAddress localAddr=IPAddress.Parse(ConfigurationManager.AppSettings[“ServerIP]”);
侦听器=新的TcpListener(localAddr,puerto);
listener.Start();
对于(int i=0;i
嗯,不清楚为什么如果这是一个WCF程序,您直接使用
Socket
TcpListener
。WCF的目的是让它为您处理网络I/O

也就是说

之所以出现异常,是因为
listener
字段在所有线程之间共享,并且一个或多个线程在第一个线程创建新的
TcpListener
对象之后,但在调用
Start()
之前,设法访问了
AcceptSocket()

你有例外真是太好了。如果你运气不好,那么你的代码可以很容易地运行而不出现异常,然后你就会有一个更难调试的问题,因为唯一的症状是,神秘的是,不是所有的侦听器都接受任何客户机

依我看,最好设计代码,这样您就有了单独的对象实例来处理每个侦听套接字(并使用非静态成员作为值)。通过这种方式,您可以确保每个侦听器都正确且独立地运行

但是,通过将正确的
TcpListener
对象传递给每个线程,您可以修复这里的代码,至少在异常方面是这样的:

private void StartListener()
{
    List<int> puertos = new List<int>();

    puertos.Add(5494);
    puertos.Add(5495);
    puertos.Add(5496);
    puertos.Add(5497);

    foreach (int puerto in puertos)
    {
        IPAddress localAddr = IPAddress.Parse(ConfigurationManager.AppSettings["ServerIP"]);
        TcpListener listener = new TcpListener(localAddr, puerto);
        listener.Start();

        for (int i = 0; i < LIMIT; i++)
        {
            Thread t = new Thread(() => Service(listener));
            t.Start();
        }
    }

}

private void Service(TcpListener listener)
{
    while (true)
    {
        Socket soc = listener.AcceptSocket();

        try
        {

            byte[] resp = new byte[2000];
            var memStream = new MemoryStream();
            var bytes = 0;

            NetworkStream s = new NetworkStream(soc);
            StreamReader sr = new StreamReader(s);

            while (true)
            {
                string trama = "";
                if (s.CanRead)
                {
                    do
                    {
                        bytes = s.Read(resp, 0, resp.Length);
                        trama = Util.Util.ByteArrayToHexString(resp);
                    }
                    while (s.DataAvailable);
                }

                if (trama == "" || trama == null) break;    
            }
            s.Close();
        }
        catch (Exception e) { }
        finally
        {
            soc.Close();
        }
    }
}
private-void-istener()
{
List puertos=新列表();
普埃尔托斯增补本(5494);
普埃尔托斯增补本(5495);
普埃尔托斯增补本(5496);
普埃尔托斯增补本(5497);
foreach(普埃尔托斯港内)
{
IPAddress localAddr=IPAddress.Parse(ConfigurationManager.AppSettings[“ServerIP]”);
TcpListener listener=新的TcpListener(localAddr,波多黎各);
listener.Start();
对于(int i=0;i服务(侦听器));
t、 Start();
}
}
}
专用void服务(TcpListener侦听器)
{
while(true)
{
Socket soc=listener.AcceptSocket();
尝试
{
字节[]resp=新字节[2000];
var memStream=new MemoryStream();
var字节=0;
网络流s=新网络流(soc);
StreamReader sr=新的StreamReader;
while(true)
{
字符串trama=“”;
如果(s.CanRead)
{
做
{
字节=s.Read(分别为,0,分别为长度);
trama=Util.Util.ByteArrayTohextString(resp);
}
而(s.DataAvailable);
}
如果(trama==“”| | trama==null)中断;
}
s、 Close();
}
捕获(例外e){}
最后
{
soc.Close();
}
}
}
确保删除
静态TcpListener侦听器字段


最后一点注意:您永远不应该捕获异常,除非在代码的某一部分中,将发生的一切是,选择性地记录异常并终止进程。

嗯,不清楚为什么如果这是一个WCF程序,您直接使用的是
套接字
TcpListener
。WCF的目的是让它为您处理网络I/O

也就是说

之所以出现异常,是因为
listener
字段在所有线程之间共享,并且一个或多个线程在第一个线程创建新的
TcpListener
对象之后,但在调用对象之前,设法访问了
AcceptSocket()