Reputation: 974
I'm not to acquainted with TcpListener
and sockets
, but I have the following code that execute correctly sometimes in my Initializer class from my App_Code of my Wcf project, but then the first correct execute it show me errors sometimes and then execute correctly other ones without pattern.
The error stop in this line code:
Socket soc = listener.AcceptSocket();
And then shows this aditional information:
Additional Information: Not in Listening. Call the Start () method before calling this method.
But like you can see I call start method before listener.AcceptSocket()…
I suspect that this is for try to begin a init daemon in a WCF project.
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();
}
}
}
Upvotes: 2
Views: 570
Reputation: 70652
Well, it's not clear why if this is a WCF program, you are using Socket
or TcpListener
directly. The point of WCF is to let it handle the network I/O for you.
That said…
You are getting the exception because the listener
field is shared between all of your threads and one or more of your threads has managed to get to AcceptSocket()
just after the first thread has created a new TcpListener
object, but before it's called Start()
.
It's actually good you got the exception. Your code could easily have run without that exception, if you were unlucky enough, and then you'd have a much harder problem to debug because the only symptom would be that, mysteriously, not all of your listeners were accepting any clients.
IMHO, it would be best to design the code, such that you have separate object instances handling each listening socket (and use non-static members for values). That way, you can be sure each listener is operating correctly and independently.
But, the code you have here can be fixed, at least with respect to the exception, by passing the correct TcpListener
object to each thread:
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();
}
}
}
Be sure to remove the static TcpListener listener;
field.
One last note: you should never catch Exception
, except in a part of the code where all that will happen is that, optionally the exception is logged, and the process is terminated.
Upvotes: 1