Problem TCP blocks


Discuss-gnuradio mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/discuss-gnuradio

Hi Andy,

oh yes, I don’t like that block :wink: but I’m happy it’s there.

So the problem lies in the way this block is structured, and how GNU
Radio runs:

tcp_sink is just a hier block – it’s nothing but a small wrapper around
the file_descriptor_sink[1]. The cool thing about sockets is that you
can, as soon as you have a connection, get a file descriptor for that
connection and read and write from/to it, just like a file.
So tcp_sink just sets up a listening socket, and as soon as that
connects, it uses the resulting file descriptor [2] to set up a
file_descriptor_sink.
That is all nice – but: this means that the constructor of tcp_sink
blocks for as long as it takes till someone connects to this socket.
Which means that the script setting up your flow graph just pauses for
as long as it waits for the first socket to get its connection set up;
the second socket is not in listening mode, yet, at this point. So
you’re doing everything right, it’s just so that your second tcp server
isn’t even created before the first one connects!

In principle, this is something you’d avoid; waiting for sockets to
connect is typically the job of a gr::block::start() method rather than
a gr::hier_block2’s constructor, for exactly this reason. However,
tcp_sink is there for “historical reasons”, and it’s mightily handy in
many cases.

If your application doesn’t scream for performance:
You might just want to use gr_modtool to create a python source, let
that block’s constructor set up a socket where you call sock.listen(),
and give that block a start(self) method, which calls sock.accept, and
stores the returned connected socket in a property of the block; work()
would then write to that socket. Something like [3]

def start(self):
    """
    Block start method, called when user calls tb.run/tb.start
    """
    self.connection, _ = self.listener.accept()

def stop(self):
    self.connection.close()
    self.listener.close()


def work(self, input_items, output_items):
    in0 = input_items[0]
    nbytes = len(in0)*self.itemsize
    nnext = nbytes // self.itemsize * self.itemsize
    last_pos = 0
    sent = 0
    remaining = nbytes
    rawbuffer = in0.data

    while nnext:
        sent =

self.connection.send(rawbuffer[last_pos:last_pos+nnext]) #um, yeah.
if not sent: ## we couldn’t send a single byte →
connection is dead
self.connection.close()
return -1 ## We’re done.
remaining -= sent
last_pos += sent
nnext = remaining // self.itemsize * self.itemsize # to make
sure we only send whole items
return sent // self.itemsize

[1]
http://gnuradio.org/doc/doxygen/classgr_1_1blocks_1_1file__descriptor__sink.html
[2]
https://github.com/gnuradio/gnuradio/blob/master/grc/grc_gnuradio/blks2/tcp.py#L70
[3]

really, just wrote this in a hurry. didn’t even care to syntax check.
for illustration purposes only.


Discuss-gnuradio mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/discuss-gnuradio