Only one usage of each socket address (protocol/network address/port)is normally permitted

P

pbd22

Hi. I am getting the below error:


Event Type: Error
Event Source: PeskyService
Event Category: None
Event ID: 0
Date: 1/30/2008
Time: 5:49:10 PM
User: N/A
Computer: Computer
Description:
Only one usage of each socket address (protocol/network address/port)
is normally permitted


The service is starting (successfully) and then throwing this error
immediately after. It does this about 1,900 times in a very short
period of time and then throws an event log too full error.

I am not closing something when I should be - I feel. I have provided
the relevant methods (I think) showing where stuff gets opened and
closed.

The methods are:

protected override void OnStart(string[] args)
{
this.timer1.Enabled = true;
new Thread(new ThreadStart(Listen)).Start();

}

protected override void OnStop()
{
this.timer1.Enabled = false;
base.OnStop();

}


public void Listen()
{

Queue unsyncq = new Queue();
connectionQueue = Queue.Synchronized(unsyncq);

try
{

TcpListener listener = new TcpListener(_telnetServer,
_telnetPort);
listener.Start();

while (true)
{

_telnetSocket = listener.AcceptTcpClient();
connectionQueue.Enqueue(_telnetSocket);

Thread workingthread = new Thread(new
ThreadStart(TheConnectionHandler));
workingthread.Start();

}

}
catch (Exception e)
{
eventLog2.WriteEntry("Error in Listener:" + e.Message,
EventLogEntryType.Error);
return;
}

}

....


public void TheConnectionHandler()
{

_telnetSocket = (TcpClient)connectionQueue.Dequeue();
_clientStream = _telnetSocket.GetStream();

while (true)
{

_bytesRead = 0;

try
{

_bytesRead = _clientStream.Read(message, 0,
4096); //message

}
catch
{
//a socket error has occured
break;
}
if (_bytesRead == 0)
{
break;
}

statusMessage += ASCII.GetString(message, 0,
_bytesRead);

[SNIP]

_telnetSocket.Close();
_clientStream.Close();
}
 
A

Anil TG

This normally happens when a client tries to connect on a socket on which
another connection has already been accepted...
 
J

Jon Skeet [C# MVP]

Anil TG said:
This normally happens when a client tries to connect on a socket on which
another connection has already been accepted...

No, not quite - if you try to connect to a socket and it's been
accepted, it will be queued for the server to call Accept again.

The OP's situation is when you try to *listen* on a socket which is
already being listened on.
 
P

pbd22

OK, thanks.
I sort of figured that but am unclear where exactly to post the stop
command.
If I do something like the below, the intllisense tells me that
listener.stop() will
never be reachable. Where, exactly, do i call stop??

Thanks.


TcpListener listener = new TcpListener(_telnetServer,
_telnetPort);
listener.Start();

while (true)
{

_telnetSocket = listener.AcceptTcpClient();
connectionQueue.Enqueue(_telnetSocket);

Thread workingthread = new Thread(new
ThreadStart(TheConnectionHandler));
workingthread.Start();

}


listener.Stop();
 
P

pbd22

anybody care to address the OP? :)

Should I be flusing my queue and closing the listener?
If so, where exactly should I be placing my closing logic?

I'd appreciate any help here. Thanks!
 
J

Jon Skeet [C# MVP]

pbd22 said:
The service is starting (successfully) and then throwing this error
immediately after. It does this about 1,900 times in a very short
period of time and then throws an event log too full error.

Are you sure that the server isn't already listening on the port?

I'm surprised that it happens more than once, as I'd expect it to just
throw the exception once in Listen and then stop.
 
P

pbd22

Are you sure that the server isn't already listening on the port?

I'm surprised that it happens more than once, as I'd expect it to just
throw the exception once in Listen and then stop.

John,

Thanks.

I have disabled Telnet. I don't know what else would be listening on
port 23 but I don't see anything
when I run NETSTAT. Do you know a way to stat all listeners on port
23? I couldn't figure that one out.

Otherwise, yes. It opens and closes with the error immediately when
the service starts. I get like 400
of these in the first second. The exception is definitely repeating in
some sort of endless loop.

Peter
 
J

Jon Skeet [C# MVP]

pbd22 said:
Thanks.

I have disabled Telnet. I don't know what else would be listening on
port 23 but I don't see anything
when I run NETSTAT. Do you know a way to stat all listeners on port
23? I couldn't figure that one out.

Try telnetting to it before you run your service.
Otherwise, yes. It opens and closes with the error immediately when
the service starts. I get like 400
of these in the first second. The exception is definitely repeating in
some sort of endless loop.

Hmm. It would be good to put some more logging in, to find out why it's
looping. I'd have expected the exception to come at listener.Start(),
but I haven't checked the docs.

An alternative is that you don't have the relevant security permissions
to listen on that port, but that the exception has misdiagnosed the
problem.

What happens if you try port 12345 for example?
 
P

Peter Duniho

OK, thanks.
I sort of figured that but am unclear where exactly to post the stop
command.
If I do something like the below, the intllisense tells me that
listener.stop() will
never be reachable. Where, exactly, do i call stop??

Where you call it now would be fine, if you had any way to exit the loop.
So, one fix is to change the loop so there's a way to exit it. :)

Personally, I wouldn't bother with the loop. I'd use the asynchronous API
so that I didn't have a thread sitting blocked at a call to an Accept
method, and thus I could stop and close the socket wherever I like without
worrying about some thread that I needed to coordinate with.

But barring that, another alternative would be to put a try/catch around
the call to AcceptTcpClient() and then just stop the listening socket from
somewhere else when you need to shut down the service. Then you catch the
exception that's thrown when the socket is stopped and closed, and in that
way detect that it's time to exit the loop (of course, in that scenario
there's no need to call Stop() after the loop, since calling Stop() and
Close() would be what got you out of the loop in the first place :) ).

Pete
 
P

pbd22

Thanks Pete.

So, something like this?

TcpListener listener = new TcpListener(_telnetServer, _telnetPort);
listener.Start();

while (true)
{


try
{
_telnetSocket = listener.AcceptTcpClient();
}
catch (Exception)
{
break;
}
finally
{
connectionQueue.Enqueue(_telnetSocket);
Thread workingthread = new Thread(new
ThreadStart(TheConnectionHandler));
workingthread.Start();
}

}

And, elsewhere in the program, when it is time to exit, i call:

_telnetSocket.Close()?

Thanks again,
Peter
 
P

Peter Duniho

Thanks Pete.

So, something like this?

No, definitely not. The "finally" clause will _always_ execute, whether
an exception occurs or not. You don't want to go starting up a new client
connection thread if AccepTcpClient() throws an exception.

So, skip the "finally" clause...just leave that code outside the try/catch
block, and leave the "break" in the "catch" clause so that the loop exits
when an exception is thrown.

Pete
 
P

pbd22

Pete:

What exactly am I doing wrong here?

Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.

I pretty easy stab is that I have closed my network stream and i am
trying to open it again.
What I don't get is that the prior connection closed everything and
the next user has to log on again (telnet 192.22.23.4).
So, shouldn't the new session open the stream as it always does?

Peter
 
P

Peter Duniho

What exactly am I doing wrong here?

Almost impossible to tell, as you've provided almost no information.

You may not be doing anything wrong at all. Or your entire design could
be completely fubar.
Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.

Where do you get this exception? If it's somewhere that you expected the
object to not be disposed, then the answer is to not do that after you've
disposed the object.
I pretty easy stab is that I have closed my network stream and i am
trying to open it again.

What does "I pretty easy stab" mean? I can't parse that.

In any case, it looks more like you're trying to _use_ a NetworkStream
instance that you'd already gotten. I doubt you've got any code that
actually opens a NetworkStream anyway...more likely you just get one from
the TcpClient instance.
What I don't get is that the prior connection closed everything and
the next user has to log on again (telnet 192.22.23.4).
So, shouldn't the new session open the stream as it always does?

Who knows. You didn't provide any real information about where and when
this exception happens, so it's not really possible to answer any
questions about why it might happen. Assuming the TcpListener() itself
hasn't been closed, and assuming that when a new client attempts to
connect after a previous client has disconnected, and assuming that you
are making sure that you are using a brand-new TcpClient with the new
client, and assuming that you refresh any previously-obtained data that
you might have gotten from an old TcpClient, then the exception shouldn't
happen.

Since it does, presumably you've made a mistake somewhere that violates at
least one of those assumptions. You should look for such a violation, and
if you find one that's probably your problem.

Pete
 
P

pbd22

Thanks.

I think the "refreshed data" may be my problem. How do I ensure that,
on the next
connection, the buffer is clean and that no "old" data will be
processed?

For what it is worth, If something goes bad in my program (either via
user logic or program error) this is
what i use:

private void SendResponse(string message)
{

//add some message to the buffer here...

_clientStream.Write(buffer, 0, buffer.Length);
loginState = LoginState.Login;
_telnetSocket.Close();

}


Here is my handler that sets up the connection

public void TheConnectionHandler()
{

_telnetSocket = (TcpClient)connectionQueue.Dequeue();
_clientStream = _telnetSocket.GetStream();

buffer = ASCII.GetBytes(" ");
_clientStream.Write(buffer, 0, buffer.Length);
_clientStream.Flush();

while (true)
{

_bytesRead = 0;

try
{

//blocks until a client sends a message
_bytesRead = _clientStream.Read(message, 0,
4096); //message

}
catch
{
//a socket error has occured
break;
}
if (_bytesRead == 0)
{
break;
}

statusMessage += ASCII.GetString(message, 0,
_bytesRead);

// and so on...

PS. "I pretty easy stab = A pretty easy stab". Was typing fast.
 
P

pbd22

Yeah, its the statusMessage variable.

Its not clean when a new connection happens.

A clean version is:

statusMessage = <x><y></y><z></z></x>

When the error happens, statusMessage reads:

statusMessage = <x><y></y><z></z></x><

the last "<" must have carried over from the former connection.

How do I make sure this doesn't happen?

Thanks.
Peter
 
P

Peter Duniho

Thanks.

I think the "refreshed data" may be my problem. How do I ensure that, on
the next
connection, the buffer is clean and that no "old" data will be
processed?

Well, the easiest way is to dedicate a class to each connection. It's
something I've suggested before. Don't put data that's specific to a
given connection into a class that's available more globally. Put it in a
class that is instantiated for each connection. Then you are guaranteed
that only that connection will use that data.

The alternative is to guarantee that you only have one connection at a
time, and that a thread dedicated to one client is always done using the
shared data before a new thread dedicated to a new client is started.

It's _possible_ that your code complies with this latter requirement (it
obviously does not comply with the former), but it's hard to know for
sure. Basically, your main accept loop should not proceed to accepting a
new client until it has received a signal from the client-dedicated thread
that it's done using the shared data.

All that said, you still haven't said where the exception you're asking
about was thrown. Without knowing that, there's not even any way to
speculate as to what's wrong, never mind provide any detailed suggestion
as to how to avoid it.

Pete
 
P

Peter Duniho

[...]
When the error happens, statusMessage reads:

statusMessage = <x><y></y><z></z></x><

the last "<" must have carried over from the former connection.

How do I make sure this doesn't happen?

Well, again...the best way is to not use the same "statusMessage" variable
for multiple connections. Use a connection-dedicated class to store
connection-specific data.

But if you're not going to do that, you simply need to make sure you reset
the variable's state before starting to handle a new connection. E.g. set
"statusMessage" to "" when you initialize the other variables (like the
TcpClient variable and the NetworkStream variable).

Pete
 
P

pbd22

Thanks Pete.

Moving statusMessage into the separate class I created for all the
other connection-specific
properties worked. I should have thought of that as you suggested it
before. For some reason
I thought it belonged outside that class. Anyway, thanks - that
worked.

I have one last question. There are times when I pass arguments to the
custom telnet that the logic
doesn't know what to do with and the application simply hangs with no
response. This can be for
any number of reasons - the user typed some garbage, the user typed
the correct start sequence
but didn't close the tag properly, or whatever. Basically, how do I
handle a hanging connection???
I also find, sometimes, that when the connection hangs and I press CTL-
C the telnet server responds
with the correct response (failure flag and reason for error).

Is there a way of setting a timer that, lets say, acknowledges the
established connection and then
sets a time-out flag. If the TheConnectionHandler theread starts
before that time, then we are good.
But, if the connection is estableished but TheConnectionHandler does
not fire and the time-out flag
is reached, then the user gets a time-out response. Does that sound
like the way to go?

Thanks again,
Peter
 
P

Peter Duniho

[...]
Is there a way of setting a timer that, lets say, acknowledges the
established connection and then
sets a time-out flag. If the TheConnectionHandler theread starts
before that time, then we are good.
But, if the connection is estableished but TheConnectionHandler does
not fire and the time-out flag
is reached, then the user gets a time-out response. Does that sound
like the way to go?

I can't say that I really understand the question. It's not clear to me
from your description where the "hanging" behavior is occurring. Is the
client not sending data to the server as it should? Is the server getting
confused about data that is sent to it, and thus not responding?

If the latter, then IMHO the correct solution is to make the server more
robust. It should be able to handle invalid input gracefully, just as any
program should be able to handle invalid input gracefully. What
"gracefully" means depends on the context, but in this case I would say
that sending an error message to the client and resetting the server state
to whatever it was before the bad input was received would work well.

If the former, then yes...you can certainly implement a timeout on the
server. If you know for a fact that there is some time past which you
definitely want to do something, then it's simple enough to implement a
timer for this purpose. Use the System.Timers.Timer class, configure it
to fire once, and when it does check to see if there's been any activity
yet. If there hasn't been, do whatever you think is appropriate. This
might simply be to close the connection, or it might be to send some
message to the client, prompting the user again. It all depends on your
particular situation what's the best action to take.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top