Socket Attributes

I’m having trouble accessing attributes from the python socket module. I can bind to an address and send and receive messages but can’t set blocking or set socket options. For instance:


ip = '127.0.0.1'
port=23072
buffer = 1024

import socket
		
addr = (ip,port)
Sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
Sock.bind(addr)

test=0
while test==0:
	print 'Listening on port %d....'%(port)
	Sock.setblocking(0)
	#data,addr = Sock.recvfrom(buffer)
	test = 1

This works in newer versions of Jython and Python, but get an attribute error on Sock.setblocking() in Ignition. The same thing happend with other attributes I’ve tried. Ideas?

Honestly, troubleshooting advanced non-blocking Python IO libraries is beyond the scope of what we can offer. My guess is that the version of Python we are using doesn’t have the native hooks that are needed to offer non-blocking IO, which is a very low-level feature.

I’d switch to using the Java libraries (java.nio) instead (through Python).

It was more of a python question than a socket question anyway. I assume that if an attribute doesn’t show up with a dir(), it isn’t available, right?

This is just something that I’m porting over to Ignition and which is already working very well in jython, but I’m going to take a good look at java.nio. It looks like there are definitely more options.

Here is an example of how you could use plain Java DatagramSockets to listen for UDP packets. This code will receive 10 ascii messages and then stop listening.

[code]from jarray import zeros
from java.net import DatagramSocket, DatagramPacket, InetAddress
from java.lang import String

packet = DatagramPacket(zeros(1024, ‘b’), 1024)

listening port & address

port = 3001
addr = InetAddress.getByName(“127.0.0.1”)

socket = DatagramSocket(port, addr)

try:
for x in range(10):
socket.receive(packet)
data = String(packet.data, packet.offset, packet.length)
print “Received packet from %s: ‘%s’” % (packet.address, data)
finally:
socket.close()[/code]

Most excellent. I copied this into my existing code, and it’s cranking away as I type this. You guys came through as usual.

I have a couple of questions though:

  1. How is that java string different from a python string? I had to do a data = str(data) before I could do a data[2:10], for instance.

  2. I’m receiving a byte stream anyway. Should I be using java.nio.ByteBuffer instead? I’m using struct.unpack, and the only portion that I interpret as a string is the header.

I had to get it working in a hurry, but I’ll take the time tonight and read up a lot more on this. Thanks again.

Great, glad its working out for you!

  1. The difference is somewhat boring. It is that a Java string is an instance of [tt]java.lang.String[/tt] and a Jython string is a [tt]org.python.core.PyString[/tt] which is a wrapper around a Java string that supports the Python string operations (such as slicing, which is what you’re example shows). The only reason I made a Java string is that I didn’t readily know how to turn a byte[] into a Jython string.

  2. I wouldn’t mess with ByteBuffers if you don’t have to. They are mainly used in the [tt]java.nio[/tt] package which supports non-blocking IO, but I wouldn’t go there unless you are forced to by performance needs. It is much harder to work with.

Thanks Carl. I’ll explore the non-blocking stuff eventually on another PC, but for now it works great.

Another question: What is the default encoding in Ignition? The only thing I had to change in my code was how the byte conversion was handled. In the top example, this is how it works when developed in the Eclipse environment; in the bottom example, to get the same output in Ignition, I had to add the [-3:] (my goal is to output the literal hex value as a two character string, i.e 32=‘20’):

a=[]
for i in range(-10,10):
	a.append(i)

Output = ''.join( [ "%02X " % ord( x ) for x in a ] ).strip()

print Output, '\n'


a=[]
for i in range(-10,10):
	a.append(i)

Output = ''.join( [ ("%02X " % ord( x ))[-3:] for x in a ] ).strip()

print Output

I don’t think it has anything to do with the jython version, because I have to add the [-3:] when I run the code in the Netbeans environment as well. I’ve tweaked very encoding setting I could find in Netbeans, but it didn’t make a difference. I can live with it, since the [-3:] is redundant if the output comes out as two characters anyway, but it’s more of a curiousity factor since I will be doing a lot of text manipulation in the future. Just want to understand what’s going on.

You’re saying that [tt]"%02X"%-1[/tt] evaluates to [tt]“FF”[/tt] in your Eclipse environment? That is suprising, since the [tt]“2”[/tt] is a minimum formatted length - I’d say that the behavior displayed in NetBeans and Ignition is more correct.