Discussion:
10048 WSAEADDRINUSE "Address already in use" Error
(too old to reply)
Gregory A. Dunn
2004-09-29 14:03:55 UTC
Permalink
Hello,

I am using the TTcpClient object in a multi-threaded application to
simultaneously communicate to several field devices. I am using one
TTcpClient object in each of my communications threads. The application
seems to work pretty well for the most part but I get the following Winsock
Error on a regular basis: Any suggestions on resolving the problem would be
much appreciated. Details on the issue are show below:

###################################
WSAEADDRINUSE

(10048)

Address already in use.

Only one usage of each socket address (protocol/IP address/port) is normally
permitted. This error occurs if an application attempts to bind a socket to
an IP address/port that has already been used for an existing socket, or a
socket that wasn't closed properly, or one that is still in the process of
closing. For server applications that need to bind multiple sockets to the
same port number, consider using setsockopt
(SO_REUSEADDR). Client applications usually need not call bind at all -
connect will choose an unused port automatically.
#####################################

I use the following sequence to open, communicate and then close the
connections:: This code only gives the general sequence, the actual code
is complex with error handling etc. Extra code has been removed for this
example.

TCPClient.Open;

repeat
BytesRead := TCPClient.ReceiveBuf(RxBuf,RxBufSize);
// dosomething with received data

// send out data if necessary
if [Needed] then
TCPClient.Sendln(MsgSendStr,'');

until [Finished Processing]

TCPClient.Close;


After communications is complete with one unit, there is a delay of one
secnod and then the process is repeated with another unit.

In my testing, I have 5 units in the test which are communicated with
repeatadly in this fashion. The error seems to occur every 1-15 minutes or
so.

How can I work around this problem?

Thanks,
Greg Dunn
***@eagleresearchcorp.com
304-757-6565 ext 117
Gavin Watkinson
2004-09-29 15:11:57 UTC
Permalink
You have one item listening on a port for data to come in, another item
then tries to listen on the same port, causing the error.

Have one client open for all the machines to talk to, dont keep opening
and closing, then have some way to distinguish which machine is which.

Gavin
Post by Gregory A. Dunn
Hello,
I am using the TTcpClient object in a multi-threaded application to
simultaneously communicate to several field devices. I am using one
TTcpClient object in each of my communications threads. The application
seems to work pretty well for the most part but I get the following Winsock
Error on a regular basis: Any suggestions on resolving the problem would be
###################################
WSAEADDRINUSE
(10048)
Address already in use.
Only one usage of each socket address (protocol/IP address/port) is normally
permitted. This error occurs if an application attempts to bind a socket to
an IP address/port that has already been used for an existing socket, or a
socket that wasn't closed properly, or one that is still in the process of
closing. For server applications that need to bind multiple sockets to the
same port number, consider using setsockopt
(SO_REUSEADDR). Client applications usually need not call bind at all -
connect will choose an unused port automatically.
#####################################
I use the following sequence to open, communicate and then close the
connections:: This code only gives the general sequence, the actual code
is complex with error handling etc. Extra code has been removed for this
example.
TCPClient.Open;
repeat
BytesRead := TCPClient.ReceiveBuf(RxBuf,RxBufSize);
// dosomething with received data
// send out data if necessary
if [Needed] then
TCPClient.Sendln(MsgSendStr,'');
until [Finished Processing]
TCPClient.Close;
After communications is complete with one unit, there is a delay of one
secnod and then the process is repeated with another unit.
In my testing, I have 5 units in the test which are communicated with
repeatadly in this fashion. The error seems to occur every 1-15 minutes or
so.
How can I work around this problem?
Thanks,
Greg Dunn
304-757-6565 ext 117
Martin James
2004-09-29 15:32:39 UTC
Permalink
Post by Gavin Watkinson
You have one item listening on a port for data to come in, another item
then tries to listen on the same port, causing the error.
Have one client open for all the machines to talk to, dont keep opening
and closing, then have some way to distinguish which machine is which.
Gavin
Gregory's app is a little odd, with all that connecting, reconnecting &
polling. I too, would think that leaving the connections open would be
better, especially with only 5 servers.

Nevertheless, how could 'Address already in use' occur at a TCP client? I
can understand that the number of client sockets could easily run out on the
crappier OS, eg W98, if there was a lot of open/close that used up sockets
faster than they could be recycled by winsock, (since it takes 2 mins
default for the wait timer to expire). But would this not give a different
error message? I'm sure I've done this with a server test app that
created/opened/closed lots of clients & the error was not 10048.

Rgds,
Martin
Gavin Watkinson
2004-09-29 16:33:54 UTC
Permalink
Saw the error msg and got it into my head it was a server - doh.

With the indy TcpClient are you setting the boundip and boundport
properties?

Gavin
Post by Martin James
Gregory's app is a little odd, with all that connecting, reconnecting &
polling. I too, would think that leaving the connections open would be
better, especially with only 5 servers.
Nevertheless, how could 'Address already in use' occur at a TCP client? I
can understand that the number of client sockets could easily run out on the
crappier OS, eg W98, if there was a lot of open/close that used up sockets
faster than they could be recycled by winsock, (since it takes 2 mins
default for the wait timer to expire). But would this not give a different
error message? I'm sure I've done this with a server test app that
created/opened/closed lots of clients & the error was not 10048.
Rgds,
Martin
Gregory A. Dunn
2004-09-29 16:48:42 UTC
Permalink
I am using the Delphi TTCPClient object from the Internet tab. I have also
used the TurboPower IPro TMultiIPClient with the same results. Do you think
I should give the Indy component a try as well. Would I gain anything?

I dont think the Delphi TTCPClient object has the bound ip/port.

Thanks,
Greg Dunn
Post by Gavin Watkinson
Saw the error msg and got it into my head it was a server - doh.
With the indy TcpClient are you setting the boundip and boundport
properties?
Gavin
Post by Martin James
Gregory's app is a little odd, with all that connecting, reconnecting &
polling. I too, would think that leaving the connections open would be
better, especially with only 5 servers.
Nevertheless, how could 'Address already in use' occur at a TCP client?
I
Post by Gavin Watkinson
Post by Martin James
can understand that the number of client sockets could easily run out on the
crappier OS, eg W98, if there was a lot of open/close that used up sockets
faster than they could be recycled by winsock, (since it takes 2 mins
default for the wait timer to expire). But would this not give a different
error message? I'm sure I've done this with a server test app that
created/opened/closed lots of clients & the error was not 10048.
Rgds,
Martin
Gregory A. Dunn
2004-09-29 16:43:39 UTC
Permalink
Thank you all so much for your quick responses.

My situation is a little odd. We manufacture gas flow measurement devices.
The devices are installed in the field on a gas line. The devices are
connected to the internet with several different technologies: CDPD, GPRS,
CDMA or with an IP to RS232 convertor. There may be several hundred of the
units which the host system must poll. Some of the units are solar powered
and only available during certain time windows. My test system on the bench
is a small scale system with 5 units with IP to RS232 convertors. I dont
think it's feasable to keep all connections open.

I know from watching the socket numbers that after I close a socket ,the
next time I connect, many times, the socket number is the same. This will
work for several open/close cycles. Then, for some reason, I will get the
10048 error. I guess the socket has not be properly freed up or something.
During the 2 minutes, what are the rules for reusing the socket?

Thanks,
Greg Dunn
Post by Martin James
Post by Gavin Watkinson
You have one item listening on a port for data to come in, another item
then tries to listen on the same port, causing the error.
Have one client open for all the machines to talk to, dont keep opening
and closing, then have some way to distinguish which machine is which.
Gavin
Gregory's app is a little odd, with all that connecting, reconnecting &
polling. I too, would think that leaving the connections open would be
better, especially with only 5 servers.
Nevertheless, how could 'Address already in use' occur at a TCP client? I
can understand that the number of client sockets could easily run out on the
crappier OS, eg W98, if there was a lot of open/close that used up sockets
faster than they could be recycled by winsock, (since it takes 2 mins
default for the wait timer to expire). But would this not give a different
error message? I'm sure I've done this with a server test app that
created/opened/closed lots of clients & the error was not 10048.
Rgds,
Martin
Martin James
2004-09-29 19:18:30 UTC
Permalink
Post by Gregory A. Dunn
Thank you all so much for your quick responses.
My situation is a little odd. We manufacture gas flow measurement devices.
The devices are installed in the field on a gas line. The devices are
connected to the internet with several different technologies: CDPD, GPRS,
CDMA or with an IP to RS232 convertor. There may be several hundred of the
units which the host system must poll. Some of the units are solar powered
and only available during certain time windows. My test system on the bench
is a small scale system with 5 units with IP to RS232 convertors. I dont
think it's feasable to keep all connections open.
I think that you probably can keep the connections open. With several
hundred connections, and given your h/w system, it is probably not necessary
to use several hundred threads for this. You could do - a few hundred
threads is not out of the question & would make comms coding much easier,
but it is probably not very efficient for your app/network with its slow
polling and server-specific time bands.

How about some timeWindow & server objects, like:

TonOffWindow=class
onTime:TdateTime;
offTime:TdateTime;
end;

EcommsState=(EcsDisconnected, EcsConnected,EcsPollSent,EcsBlahBlah);
EcommsCommand=(EccDeleted,EccWhatever),

TgasflowServer=class(TObject)
serverName:string;
hostName:string;
port:integer;
comms:TtcpClient;
onOffWindows:TobjectList;
command:EcommsCommand;
currentState:EcommsState;
nextActionTime:TdateTime;
function getNextEventTime:TdateTime;
end;

You could make a list of these objects, one for each server, ordered by the
time returned by 'getNextEventTime'. The object with the shortest NAT would
be at the front of the list. A timer could then time out this object. When
the timer fires, it's time to do something & you could queue the object to
some threads. A thread would get the object and, operating a state machine,
do whatever is required to perform the comms functionality, sending a poll,
trying to connect, whatever, and then calculate the time at which the next
action is required, (all this could be in the 'getNextEventTime' method), &
store it in the 'nextActionTime' field. The thread could then postMessage
the object back to the main thread, where it would be inserted in to the
time-list in the correct place, (possibly restarting the timer if it turned
out that its NAT was the shortest. This is not likely if there are a
reasonable number of servers, but you have to allow for it).

Some scheme like this would allow you to keep connections open to hundreds
of servers with a reasonable number of threads, avoiding needless socket
consumption.

A bit of twiddling with a TstringGrid or TlistView could allow you to watch
the progress of comms with the servers, add more servers, edit time windows
or delete servers quite easily in real time.

Rgds,
Martin
Gregory A. Dunn
2004-09-29 20:22:29 UTC
Permalink
Thanks for the advise. I'll give it a shot.

Greg Dunn
Post by Gregory A. Dunn
Post by Gregory A. Dunn
Thank you all so much for your quick responses.
My situation is a little odd. We manufacture gas flow measurement
devices.
Post by Gregory A. Dunn
The devices are installed in the field on a gas line. The devices are
connected to the internet with several different technologies: CDPD,
GPRS,
Post by Gregory A. Dunn
CDMA or with an IP to RS232 convertor. There may be several hundred of
the
Post by Gregory A. Dunn
units which the host system must poll. Some of the units are solar
powered
Post by Gregory A. Dunn
and only available during certain time windows. My test system on the
bench
Post by Gregory A. Dunn
is a small scale system with 5 units with IP to RS232 convertors. I dont
think it's feasable to keep all connections open.
I think that you probably can keep the connections open. With several
hundred connections, and given your h/w system, it is probably not necessary
to use several hundred threads for this. You could do - a few hundred
threads is not out of the question & would make comms coding much easier,
but it is probably not very efficient for your app/network with its slow
polling and server-specific time bands.
TonOffWindow=class
onTime:TdateTime;
offTime:TdateTime;
end;
EcommsState=(EcsDisconnected, EcsConnected,EcsPollSent,EcsBlahBlah);
EcommsCommand=(EccDeleted,EccWhatever),
TgasflowServer=class(TObject)
serverName:string;
hostName:string;
port:integer;
comms:TtcpClient;
onOffWindows:TobjectList;
command:EcommsCommand;
currentState:EcommsState;
nextActionTime:TdateTime;
function getNextEventTime:TdateTime;
end;
You could make a list of these objects, one for each server, ordered by the
time returned by 'getNextEventTime'. The object with the shortest NAT would
be at the front of the list. A timer could then time out this object.
When
Post by Gregory A. Dunn
the timer fires, it's time to do something & you could queue the object to
some threads. A thread would get the object and, operating a state machine,
do whatever is required to perform the comms functionality, sending a poll,
trying to connect, whatever, and then calculate the time at which the next
action is required, (all this could be in the 'getNextEventTime' method), &
store it in the 'nextActionTime' field. The thread could then postMessage
the object back to the main thread, where it would be inserted in to the
time-list in the correct place, (possibly restarting the timer if it turned
out that its NAT was the shortest. This is not likely if there are a
reasonable number of servers, but you have to allow for it).
Some scheme like this would allow you to keep connections open to hundreds
of servers with a reasonable number of threads, avoiding needless socket
consumption.
A bit of twiddling with a TstringGrid or TlistView could allow you to watch
the progress of comms with the servers, add more servers, edit time windows
or delete servers quite easily in real time.
Rgds,
Martin
Loading...