Gus Gus - 2 months ago 9
Python Question

WebSocket server in Python: 'module' object has no attribute 'AF_INET'

I am trying to run this simple Python WebSocket, with a couple very minor changes. I am running Python 2.4.3 because I cannot use an newer version, but I'm not sure how much that matters.

Here is the error I'm getting:

Traceback (most recent call last):
File "socket.py", line 258, in ?
server = WebSocketServer("localhost", 8000, WebSocket)
File "socket.py", line 205, in __init__
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
AttributeError: 'module' object has no attribute 'AF_INET'


And here is my code:

import time
import struct
import socket
import base64
import sys
from select import select
import re
import logging
from threading import Thread
import signal

# Simple WebSocket server implementation. Handshakes with the client then echos back everything
# that is received. Has no dependencies (doesn't require Twisted etc) and works with the RFC6455
# version of WebSockets. Tested with FireFox 16, though should work with the latest versions of
# IE, Chrome etc.
#
# rich20b@gmail.com
# Adapted from https://gist.github.com/512987 with various functions stolen from other sites, see
# below for full details.

# Constants
MAGICGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
TEXT = 0x01
BINARY = 0x02


# WebSocket implementation
class WebSocket(object):

handshake = (
"HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
"Upgrade: WebSocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Accept: %(acceptstring)s\r\n"
"Server: TestTest\r\n"
"Access-Control-Allow-Origin: http://localhost\r\n"
"Access-Control-Allow-Credentials: true\r\n"
"\r\n"
)


# Constructor
def __init__(self, client, server):
self.client = client
self.server = server
self.handshaken = False
self.header = ""
self.data = ""


# Serve this client
def feed(self, data):

# If we haven't handshaken yet
if not self.handshaken:
logging.debug("No handshake yet")
self.header += data
if self.header.find('\r\n\r\n') != -1:
parts = self.header.split('\r\n\r\n', 1)
self.header = parts[0]
if self.dohandshake(self.header, parts[1]):
logging.info("Handshake successful")
self.handshaken = True

# We have handshaken
else:
logging.debug("Handshake is complete")

# Decode the data that we received according to section 5 of RFC6455
recv = self.decodeCharArray(data)

# Send our reply
self.sendMessage(''.join(recv).strip());


# Stolen from http://www.cs.rpi.edu/~goldsd/docs/spring2012-csci4220/websocket-py.txt
def sendMessage(self, s):
"""
Encode and send a WebSocket message
"""

# Empty message to start with
message = ""

# always send an entire message as one frame (fin)
b1 = 0x80

# in Python 2, strs are bytes and unicodes are strings
if type(s) == unicode:
b1 |= TEXT
payload = s.encode("UTF8")

elif type(s) == str:
b1 |= TEXT
payload = s

# Append 'FIN' flag to the message
message += chr(b1)

# never mask frames from the server to the client
b2 = 0

# How long is our payload?
length = len(payload)
if length < 126:
b2 |= length
message += chr(b2)

elif length < (2 ** 16) - 1:
b2 |= 126
message += chr(b2)
l = struct.pack(">H", length)
message += l

else:
l = struct.pack(">Q", length)
b2 |= 127
message += chr(b2)
message += l

# Append payload to message
message += payload

# Send to the client
self.client.send(str(message))


# Stolen from http://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side
def decodeCharArray(self, stringStreamIn):

# Turn string values into opererable numeric byte values
byteArray = [ord(character) for character in stringStreamIn]
datalength = byteArray[1] & 127
indexFirstMask = 2

if datalength == 126:
indexFirstMask = 4
elif datalength == 127:
indexFirstMask = 10

# Extract masks
masks = [m for m in byteArray[indexFirstMask : indexFirstMask+4]]
indexFirstDataByte = indexFirstMask + 4

# List of decoded characters
decodedChars = []
i = indexFirstDataByte
j = 0

# Loop through each byte that was received
while i < len(byteArray):

# Unmask this byte and add to the decoded buffer
decodedChars.append( chr(byteArray[i] ^ masks[j % 4]) )
i += 1
j += 1

# Return the decoded string
return decodedChars


# Handshake with this client
def dohandshake(self, header, key=None):

logging.debug("Begin handshake: %s" % header)

# Get the handshake template
handshake = self.handshake

# Step through each header
for line in header.split('\r\n')[1:]:
name, value = line.split(': ', 1)

# If this is the key
if name.lower() == "sec-websocket-key":

# Append the standard GUID and get digest
combined = value + MAGICGUID
response = base64.b64encode(combined.digest())

# Replace the placeholder in the handshake response
handshake = handshake % { 'acceptstring' : response }

logging.debug("Sending handshake %s" % handshake)
self.client.send(handshake)
return True

def onmessage(self, data):
#logging.info("Got message: %s" % data)
self.send(data)

def send(self, data):
logging.info("Sent message: %s" % data)
self.client.send("\x00%s\xff" % data)

def close(self):
self.client.close()


# WebSocket server implementation
class WebSocketServer(object):

# Constructor
def __init__(self, bind, port, cls):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind((bind, port))
self.bind = bind
self.port = port
self.cls = cls
self.connections = {}
self.listeners = [self.socket]

# Listen for requests
def listen(self, backlog=5):

self.socket.listen(backlog)
logging.info("Listening on %s" % self.port)

# Keep serving requests
self.running = True
while self.running:

# Find clients that need servicing
rList, wList, xList = select(self.listeners, [], self.listeners, 1)
for ready in rList:
if ready == self.socket:
logging.debug("New client connection")
client, address = self.socket.accept()
fileno = client.fileno()
self.listeners.append(fileno)
self.connections[fileno] = self.cls(client, self)
else:
logging.debug("Client ready for reading %s" % ready)
client = self.connections[ready].client
data = client.recv(4096)
fileno = client.fileno()
if data:
self.connections[fileno].feed(data)
else:
logging.debug("Closing client %s" % ready)
self.connections[fileno].close()
del self.connections[fileno]
self.listeners.remove(ready)

# Step though and delete broken connections
for failed in xList:
if failed == self.socket:
logging.error("Socket broke")
for fileno, conn in self.connections:
conn.close()
self.running = False

# Entry point
if __name__ == "__main__":

logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s")
server = WebSocketServer("localhost", 8000, WebSocket)
server_thread = Thread(target=server.listen, args=[5])
server_thread.start()

# Add SIGINT handler for killing the threads
def signal_handler(signal, frame):
logging.info("Caught Ctrl+C, shutting down...")
server.running = False
sys.exit()
signal.signal(signal.SIGINT, signal_handler)

while True:
time.sleep(100)

Answer

It appears that you've named your own file socket.py, so when you import socket, you're not getting the system library (it's just re-importing the file you're currently in - which has no AF_INET symbol). Try renaming your file something like mysocket.py.