473,738 Members | 3,854 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

[Kamaelia] TCPClient: How to sense connection failure?

Hello,

I'm currently trying to implement a simulation program with Kamaelia
and need a reliable TCP connection to a data server.

From Twisted, I know that a method is called if the connection fails
by whatever reason. I tried to get the same results with Kamaelia's
TCPClient component. If I start up the component and try to connect
to a closed TCP port it fails and sends a message out of the signal
box, that's okay.

But if the connection attempt succeeds and, after some time, the
server drops the connection with full TCP handshake (FIN, FIN+ACK,
ACK), the component just hangs and does nothing. Is this by design,
or could there be an error in my setup?

Also, how long does a TCPClient component live -- or how can/should
I terminate it explicitly? I'm afraid that if I create
a "ReconnectingTC PClient" component, it could eat up memory over
long runtime with hanging TCPClients.

Regards,
Björn

--
BOFH excuse #246:

It must have been the lightning storm we had (yesterday) (last week)
(last month)

Jan 11 '08 #1
6 3588
"Bjoern Schliessmann" <usenet-mail,,...mwrote :
>I'm currently trying to implement a simulation program with Kamaelia
and need a reliable TCP connection to a data server.

From Twisted, I know that a method is called if the connection fails
by whatever reason. I tried to get the same results with Kamaelia's
TCPClient component. If I start up the component and try to connect
to a closed TCP port it fails and sends a message out of the signal
box, that's okay.

But if the connection attempt succeeds and, after some time, the
server drops the connection with full TCP handshake (FIN, FIN+ACK,
ACK), the component just hangs and does nothing. Is this by design,
or could there be an error in my setup?
Not sure about Kamelia, but I have found that when a FIN comes along,
a socket.recv() gives back an empty string, just like EOF on a file.

I always have my sockets unblocked and fitted with time outs, but then
I am basically a broken down assembler programmer, so there are probably
better techniques around.

Below is what I use - a sort of netstring, synced on a tilde, with human
readable length implementation and escaping of tildes and the escape character.

It seems to work reliably for me, and detects when the server goes down.

The code for a typical client is below. If anybody is interested I will post
the server
too, but it should be trivial to make, given the example below.

I hope the tabs survive the journey

- Hendrik

#start of code fragment

def sockget_len(s,L ,data):
"""
This fills a buffer of given length from the socket s, recursively.

s is the socket
L is the length to receive
data is the buffer
"""

error = 0
req_L = L - len(data)
try:
data = data+s.recv(req _L)
except socket.error,ms g: # broken pipes again
if 'timed out' in msg:
rec = '2'*L
return 2,rec # time out
print 'socket error while receiving',msg
rec = '1'*L
return 1,rec # error = 1 is a snafu
if not data:
print 'end of file while receiving'
rec = '0'*L
return 3,rec # This is end of file
if len(data) != L:
error,data = sockget_len(s,L ,data)
return error,data
def sockget(s):
"""
Gets a transmission from host.
"""

while True:
tilde = ''
error,tilde = sockget_len(s,1 ,tilde) # sync up on tilde
if error == 1:
return error,''
elif error == 2:
return error,''
elif error == 3:
return error,''
if tilde == '~':
break

length = ''
error,length = sockget_len(s,4 ,length) # get the length of the data
if error == 1:
return error,'' # real error
elif error == 2:
return error,'' # Time out
elif error == 3:
return error,'' # End of file
L = int(length)
buf = ''
error,data = sockget_len(s,L ,buf) # get the data of length L
return error, data # same errors as above 0 is all right
# client communications program

def comms_thread(qi ,qo):
"""This listens for the latest values, and sends requests up."""

while True:

HOST = 'Linuxbox' # The remote host
PORT = 50007 # The same port as used by the server
socket.setdefau lttimeout(10.00 )
s = socket.socket(s ocket.AF_INET, socket.SOCK_STR EAM)

while True:
try:
qi.put('Connect ing,')
s.connect((HOST , PORT))
break
except socket.error,ms g:
print 'error msg is:',msg
time.sleep(10)
continue
print 'Connected - Time out is:',s.gettimeo ut()
qi.put('Connect ed,')

last_rx_time = time.time()
last_tx_time = time.time()
while True:

while True:
error,data = sockget(s) # see if a message from host
if error == 0 and data:
msg2 = data.replace('/\x81','~')
msg1 = msg2.replace('/\xd0','/')
qi.put(msg1)
print 'received',msg1
last_rx_time = time.time()
break
elif error == 1:
print 'Error after sockget'
break
if time.time() - last_rx_time 180:
print 'no comms from host for 3 minutes'
error = 1
break # time out ok, unless they are too long
if error == 2:
error = 0 # time outs are all right here
break
if error == 3:
error = 1
break # end of files are a snafu

if error == 1:
break

try:
i_string = qo.get(block=Fa lse) # see if stuff to transmit
except Queue.Empty:
if time.time()-last_tx_time 8.5:
i_string = 'Keepalive' # if not for a while, tell server we are alive
print 'sending keepalive'
else:
time.sleep(0.1) # else wait a while and carry on
continue

msg1 = i_string.replac e('/','/\xd0')
msg2 = msg1.replace('~ ','/\x81')
length = str(len(msg2))
L = len(length)
if L == 1:
length = '000'+length
elif L == 2:
length = '00'+length
elif L == 3:
length = '0'+length
try:
s.send('~'+leng th+msg2)
last_tx_time = time.time()
except socket.error,ms g:
print 'Socket error on transmit',msg
break
time.sleep(0.1)

s.close() # Formally close the broken thing
qi.put('Quit,') # Tell main thread its hopeless

sys.exit() # Clobber this thread


Jan 12 '08 #2
Hendrik van Rooyen wrote:
Not sure about Kamelia, but I have found that when a FIN comes
along, a socket.recv() gives back an empty string, just like EOF
on a file.
That Python socket interface can detect it I'm absolutely sure --
Twisted handles it.

I even pdb'ed Kamaelia and control flow ended at a different point
in case of connection closing -- but yielded control to the
scheduler immediately and never continued.
Below is what I use - a sort of netstring, synced on a tilde, with
human readable length implementation and escaping of tildes and
the escape character.
Thank you (though I hope I won't have to mess with socket
functions ;) ).
I hope the tabs survive the journey
Looks like they morphed to spaces.

Regards,
Björn

--
BOFH excuse #77:

Typo in the code

Jan 12 '08 #3
Bjoern Schliessmann wrote:
Hello,

I'm currently trying to implement a simulation program with Kamaelia
and need a reliable TCP connection to a data server.
The behaviour you're seeing sounds odd (which is hopefully encouraging :-),
but it's not clear from the description whether its a bug in your code or
Kamaelia. One question I really have as a result is what version are you
using?

Current release version 0.5.0, the version on /trunk, or the bleeding edge
version on /branches/private_MPS_Scr atch. (I'm using the latter to run my
greylisting server - as are a few others).

All that said though, looking at the differences between versions, I'm not
convinced they're large enough to show the problem you're seeing.

I'm not about to rule out a bug I don't know about though :-)
From Twisted, I know that a method is called if the connection fails
by whatever reason. I tried to get the same results with Kamaelia's
TCPClient component. If I start up the component and try to connect
to a closed TCP port it fails and sends a message out of the signal
box, that's okay.
If you'd prefer more information in that message, please let me know.
(all components send out a message when they shutdown. For things that
send data out as one of their primary actions send out a producerFinishe d
message)
But if the connection attempt succeeds and, after some time, the
server drops the connection with full TCP handshake (FIN, FIN+ACK,
ACK), the component just hangs and does nothing. Is this by design,
or could there be an error in my setup?
It sounds like an error in your setup... but I hate saying that. (Doesn't
tell me or you what it is, and doesn't help change things to discourage or
detect mistakes in usage)

When the server drops the connection in my setups, the client disconnects
cleanly when the server dies, with the client code looking like this:
self.send(produ cerFinished(sel f,self.howDied) , "signal")

Meaning you get a message telling you how the component shutdown as well as
the fact it shutdown. (If "howDied" is None, it's just a normal shutdown -
ie as a result of being told to shut down)

The function where this is managed is runClient in the class
Kamaelia.Intern et.TCPClient.TC PClient
(fully qualified name)

The actual socket connections are handled by a class called
ConnectedSocket Adapter which manages all logic of checking for
errors, remote shutdown etc. That works the same for both servers
and clients so breakage in clients would show up as breakage in servers
as well, which would be particularly bad.
Also, how long does a TCPClient component live -- or how can/should
I terminate it explicitly? I'm afraid that if I create
a "ReconnectingTC PClient" component, it could eat up memory over
long runtime with hanging TCPClients.
That shouldn't be an issue (I hate the word "should"), but you can do this
using a carousel component. (I ought to write that as an example of how to
use the Carousel component)

In the meantime - whilst I check to see if there's a bug I didn't know
about, the following 2 cookbook entries may be of use:
* http://kamaelia.sourceforge.net/Cookbook/TCPSystems
* http://kamaelia.sourceforge.net/Cookbook/Carousels - allows you to make
something that exits reusable. It's a little awkward to get your head
around, but is quite useful when you do. (I've heard of others using
Carousel & TCPClient to make a reconnecting TCPClient in the past)

All that said, I'm not going to rule out a bug and look into it. (if you
have a simple example you find fails, please forward it to me :)

*thinks*

The following code may also be useful when debugging:

from Kamaelia.Chassi s.Pipeline import Pipeline

class PeriodicWakeup( Axon.ThreadedCo mponent.threade dcomponent):
interval = 300
def main(self):
while 1:
time.sleep(self .interval)
self.send("tick ", "outbox")

class WakeableIntrosp ector(Axon.Comp onent.component ):
def main(self):
while 1:
Q = [ q.name for q in self.scheduler. listAllThreads( ) ]
Q.sort()
print "*debug* THREADS"+ str(Q)
self.scheduler. debuggingon = False
yield 1
while not self.dataReady( "inbox"):
self.pause()
yield 1
while self.dataReady( "inbox"):
self.recv("inbo x")

Pipeline(
PeriodicWakeup( ),
WakeableIntrosp ector(),
).activate()

If you put this code somewhere before your "run" call, you'll get periodic
output to tell you what's running. When debugging manually I'd drop the
interval to 3-10 seconds or so. I use 300 for a server.

Now, off to see if I can reproduce your problem... :)

Regards,
Michael.
--
http://kamaelia.sourceforge.net/Home
http://yeoldclue.com/blog

Jan 12 '08 #4
Michael Sparks wrote:
The behaviour you're seeing sounds odd (which is hopefully
encouraging :-), but it's not clear from the description whether
its a bug in your code or Kamaelia. One question I really have as
a result is what version are you using?
Oh sorry, it's the versions from MegaPack 1.4.0.
In the meantime - whilst I check to see if there's a bug I didn't
know about, the following 2 cookbook entries may be of use:
* http://kamaelia.sourceforge.net/Cookbook/TCPSystems
* http://kamaelia.sourceforge.net/Cookbook/Carousels - allows
you to make
something that exits reusable. It's a little awkward to get
your head around, but is quite useful when you do. (I've
heard of others using Carousel & TCPClient to make a
reconnecting TCPClient in the past)
Thanks for all the information.
All that said, I'm not going to rule out a bug and look into it.
(if you have a simple example you find fails, please forward it to
me :)
Sure, here is my code (but see below ;) ):

----snip----------------------------------------------------------
from Kamaelia.Intern et.TCPClient import TCPClient
from Kamaelia.Chassi s.Pipeline import Pipeline
from Kamaelia.Util.C onsole import ConsoleEchoer, ConsoleReader
from Axon.Component import component
from Axon.Ipc import shutdownMicropr ocess, producerFinishe d

class Listener(compon ent):

Inboxes = {"inbox": "Inbox",
"control": "control signals received here",
}

Outboxes = {"outbox": "(not used)",
"signal": "(not used)"
}

def main(self):
while True:
if self.dataReady( "inbox"):
print "data from Inbox:", repr(self.recv( "inbox"))
if self.dataReady( "control"):
control_data = self.recv("cont rol")
print repr(control_da ta)
if isinstance(cont rol_data, shutdownMicropr ocess):
print "Connection could not be established"
break
elif isinstance(cont rol_data, producerFinishe d):
print "Connection closed"
break
yield 1

k = ConsoleReader(" >>")
tcp_client = TCPClient("127. 0.0.1", 1850)
listener = Listener()
Pipeline(tcp_cl ient, listener).run()
----snip----------------------------------------------------------

So I'm just using a client and a helper object to display all data
behind it. I usually start the script in one VT, and "nc -l -p
1850" in another. Using wireshark, the packet sequence is almost
identical:

Client closes connection:
C: SYN
S: SYN,ACK
C: ACK
[connection established]
C: FIN,ACK
S: FIN,ACK
C: ACK

Client closes connection:
C: SYN
S: SYN,ACK
C: ACK
[connection established]
S: FIN,ACK
C: ACK
C: FIN,ACK
S: ACK

Looks like a perfectly normal handshake to me.
The following code may also be useful when debugging:
Cool, I've been looking for a code piece like that. :)

Whoops, the TCP client does in fact quit if the server closes
connection :) For some reason, my Listener doesn't quit. I thought
it's sufficient to exit the main method in some way to quit a
component? That's what I do using "break" in the
'if self.dataReady( "control")' part of main.

Regards,
Björn

--
BOFH excuse #265:

The mouse escaped.

Jan 13 '08 #5
Bjoern Schliessmann wrote:
Whoops, the TCP client does in fact quit if the server closes
connection :)
Great - so it wasn't a problem with the TCPClient after all :-)
For some reason, my Listener doesn't quit. I thought
it's sufficient to exit the main method in some way to quit a
component? That's what I do using "break" in the
'if self.dataReady( "control")' part of main.
It is sufficient, and running with Kamaelia from /trunk, your listener does
indeed shutdown correctly - so it looks like it's a bug in that release of
Kamaelia.

That's my bad really because we haven't done a full release in quite some
time.

Looking at the old code, it appears that in that code the TCPClient wasn't
forwarding shutdown messages correctly, so there *was* a bug, but there
doesn't seem to be now.

My suggestion for the moment would be to use the code on /trunk since this
is stable at present (development happens on branches rather than /trunk)
and that I really ought to sort out the next release - I really hadn't
realised just how long it had been since the last release!

steps:

~svn co https://kamaelia.svn.sourceforge.net...kamaelia/trunk
kamaelia-trunk
~cd kamaelia-trunk
~/kamaelia-trunkcd Code/Python/Axon
~/kamaelia-trunk/Code/Python/Axonsudo python setup.py install
~/kamaelia-trunk/Code/Python/Axoncd ../Kamaelia
~/kamaelia-trunk/Code/Python/Kamaeliasudo python setup.py install

I've tested using this, and your code works as you'd expect.

Regards,
Michael.

Jan 14 '08 #6
Michael Sparks wrote:
It is sufficient, and running with Kamaelia from /trunk, your
listener does indeed shutdown correctly
Great, thanks for validating. :)
My suggestion for the moment would be to use the code on /trunk
since this is stable at present (development happens on branches
rather than /trunk)
I will.

Regards,
Björn

--
BOFH excuse #243:

The computer fleetly, mouse and all.

Jan 14 '08 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
1601
by: Michael Sparks | last post by:
Kamaelia 0.1.2 has been released! What is it? =========== Kamaelia is a collection of Axon components designed for network protocol experimentation in a single threaded, select based environment. Axon components are python generators are augmented by inbox and outbox queues (lists) for communication in a communicating sequential processes (CSP) like fashion.
3
2286
by: Michael Sparks | last post by:
Hi, I'm posting a link to this since I hope it's of interest to people here :) I've written up the talk I gave at ACCU Python UK on the Kamaelia Framework, and it's been published as a BBC R&D White Paper and is available here: * http://www.bbc.co.uk/rd/pubs/whp/whp113.shtml
6
18498
by: Michael Kennedy [UB] | last post by:
Hi, I have a project using the TcpClient and its associated NetworkStream. Everything works well except for one condition which I haven't found any information about dealing with: How do I detected when the socket connection was closed on the server-side? That is, if my client connects to the server and everything is initialized
0
1093
by: Michael Sparks | last post by:
Hi, Apologies first to those outside the UK... Open Tech 2005* is a follow on from previous years' NotCon events which are community driven low cost events by geeks & developers for geeks & developers. (Much like Pycon & Europython but much more general in nature) Website: http://www.ukuug.org/events/opentech2005/ Where/When: Hammersmith, London, UK, July 23rd
3
9100
by: Daniel | last post by:
TcpClient close() method socket leak when i use TcpClient to open a connection, send data and close the TcpClient with myTcpClientInstance.Close(); it takes 60 seconds for the actual socket on the client machine to close per my network app the computer fills up w/ thousands of these :0 TCP foobox:8888 localhost:2188 TIME_WAIT :0 TCP foobox:8888 localhost:2189 TIME_WAIT :0 TCP foobox:8888 localhost:2190 TIME_WAIT
5
9847
by: Jeff Weber | last post by:
First, my question: Should I use Write or BeginWrite (sync or async) to stream data to my clients over a TCPClient connection. Details: On the server I have a custom circular data buffer that receives byte array data representing data structures at a rate of 30ms. On a thread seperate from that which Enqueues data to the buffer I have a high performance timer that Dequeues data from the custom buffer and sends it via a tcpClient...
4
2168
by: Michael | last post by:
Hi! (OK, slightly silly subject line :) I'm extremely pleased to say - Kamaelia 0.4.0 has been released! What's New & Changed? =====================
0
1165
by: Michael Sparks | last post by:
Hello, I'd like to invite you to our first Kamaelia Open Space event. Our theme is "Making Software like Lego through intuitive useful concurrency". Perhaps you want to learn to use Kamaelia, or you're already using it, or you're simply interested in code reuse or concurrency being actually
0
1029
by: Michael | last post by:
Hi, We're (BBC Research) participating in Google's Summer of Code as a mentor organisation again, and I thought it worth spreading some extra publicity where I think there might be some interested people. (I perhaps should've sent this sooner!) * What's Google Summer of Code? (I suspect most people here know :)
0
8787
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9473
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9334
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8208
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6750
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6053
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4569
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4824
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3279
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.