<div dir="auto">Perhaps using tcp (connection oriented) sockets, so you don&#39;t have to search for the IP of the other end?  </div><div class="gmail_extra"><br><div class="gmail_quote">On Feb 3, 2017 3:40 AM, &quot;Alex Carver&quot; &lt;<a href="mailto:agcarver%2Bale@acarver.net">agcarver+ale@acarver.net</a>&gt; wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I&#39;ve been trying to figure out a method of tracking some sockets but I<br>
keep running into roadblocks.<br>
<br>
I&#39;ve got a small daemon python script that runs a thread to accept<br>
connections from remote devices.  All the basic stuff is working so no<br>
problems there.  What I&#39;m trying to do is make an asynchronous queue for<br>
the thread so I can send data back towards those devices.<br>
<br>
The queue idea was to put the device IP address and the data to send<br>
into the queue (all IPs are static and known).  The daemon thread loops<br>
continuously looking for status updates from the remote devices (via<br>
select() ).  At the end of the loop, it would check the queue for new<br>
items and send the data to the appropriate device.<br>
<br>
I currently keep a list of the socket objects that get created for every<br>
new connection.  This list gets fed into select() during each loop to<br>
tell me where there&#39;s data waiting to be received from some device.  The<br>
devices don&#39;t send regular updates on a rapid basis.  Instead they<br>
maintain an open connection and send updates once every couple minutes<br>
unless some event occurs and then they send an immediate update.<br>
<br>
Problem: I don&#39;t want to wait for one of the devices to send its message<br>
so I can send the data back.  I want to send as soon as the data is in<br>
the queue.<br>
<br>
First brute force solution is to loop through all the available sockets,<br>
check to see if the remote IP matches the one in the queue, then send<br>
data to it.  Works but can get bogged down as it does a getpeer() (to<br>
get the remote IP) on each socket until it finds a match.<br>
<br>
I didn&#39;t like that idea so I thought about two related lists.  One was<br>
keyed on the IP and the other keyed on the socket.  The IP key works<br>
fine but you can&#39;t use an object as a key in Python.  The reason for the<br>
second list keyed on socket is to avoid having to run through the IP<br>
keyed array looking for a matching value when trying to purge a dead<br>
socket (i.e. looping through the list of socket objects that select()<br>
returned, if one is dead you can&#39;t do a getpeer() on it so go to the<br>
second list, search for the socket ID and get its IP)<br>
<br>
Ok, so next idea was to use the file descriptor of the socket to get<br>
around the key problem.  I thought that was going to work until I ran<br>
into the hiccup of the socket possibly disappearing (timed out<br>
connection, device powers off, etc.) When the socket closes for whatever<br>
reason, the file descriptor goes away although the object persists until<br>
it&#39;s garbage collected after explicitly close()d.  If the file<br>
descriptor vanishes, I can&#39;t use it to purge the lists.<br>
<br>
So I&#39;m trying to figure out if there&#39;s a more persistent identifier<br>
available that can be used as a key and will persist through a socket<br>
termination and can also be used to reference the socket it came from<br>
<br>
<br>
<br>
The gist of the daemon (this runs in a loop) in rough Python (some<br>
pseduo-Python for brevity):<br>
<br>
read,write,error = select(socketlist, [], [], 0) # no blocking<br>
<br>
for s in read:<br>
        if s == the_server_socket:<br>
                client, address = s.accept()<br>
                socketlist.append(client)<br>
                #right here I would want to add:<br>
                client_track_list_by_ip[<wbr>address] = client.identifier<br>
                client_track_list_by_<wbr>identifier[client.identifier] = ip<br>
<br>
        else:<br>
                #this was a client device, do things<br>
<br>
<br>
        #this bit of code runs in various places<br>
        #the idea is to remove the socket from the<br>
        #socketlist if it&#39;s dead<br>
<br>
        (if the socket is dead or caused an error):<br>
                socketlist.remove(s)<br>
                #here I would attempt to purge the two tracking lists<br>
                #get peer won&#39;t work here because the socket<br>
                #isn&#39;t connected, go find it in the other list<br>
                ip = client_track_list_by_<wbr>identifier[s.identifier]<br>
                del client_track_list_by_ip[ip]<br>
                del client_track_list_by_<wbr>identifier[s.identifier]<br>
                s.close()<br>
<br>
<br>
#then the queue handling:<br>
while ( queue is not empty ):<br>
        queue_item = getfromqueue()<br>
<br>
        send_to_socket(client_track_<wbr>list_by_ip[queue_item.ip], queue_item.data)<br>
<br>
______________________________<wbr>_________________<br>
Ale mailing list<br>
<a href="mailto:Ale@ale.org">Ale@ale.org</a><br>
<a href="http://mail.ale.org/mailman/listinfo/ale" rel="noreferrer" target="_blank">http://mail.ale.org/mailman/<wbr>listinfo/ale</a><br>
See JOBS, ANNOUNCE and SCHOOLS lists at<br>
<a href="http://mail.ale.org/mailman/listinfo" rel="noreferrer" target="_blank">http://mail.ale.org/mailman/<wbr>listinfo</a><br>
</blockquote></div></div>