WinError 10038 in a child class of socket in Python 3 - python

I made the follow class:
class Client(socket.socket):
def __init__(self):
super(Client, self).__init__()
self.settimeout(None)
self.radd = None
self.port = None
self.buffersize = None
def connect_to_server(self):
self.connect((self.radd, self.port))
def configure(self, radd:str, port=49305, buffersize=2048):
# close the socket
self.close()
# assign a new configuration
self.radd = radd
self.port = port
self.buffersize = buffersize
and i used it as follow:
c = Client()
c.configure('192.168.1.1')
c.connect_to_server()
but i get the error: [WinError 10038]
Can anyone tell me why this happens?

Error 10038 is WSAENOTSOCK.
An operation was attempted on something that is not a socket.
It is happening because you are closing the socket before you connect. If you call close(), you have to create a new socket after that.

Related

Python super init custom socket class

I would like to write a class which inherits the functionalities of socket.
So my code looks like this:
class walkie_talkie(socket.socket(socket.AF_INET, socket.SOCK_STREAM)):
def __init__(self):
self.BUFFERSIZE = 8192
self.STATE = None
self.IP = None # Server IP
self.PORT = 5000
self.NUMBER_OF_UNACCEPTED_CONNECTIONS = 1
self.bytestream = None
super().__init__()
And I use this class as:
from walkie_talkie import walkie_talkie
rpi1 = walkie_talkie()
So I thought using super().__init__() inherits functions of socket.socket(socket.AF_INET, socket.SOCK_STREAM)
However, I receive this error:
File "...\lib\socket.py", line 151, in __init__
_socket.socket.__init__(self, family, type, proto, fileno)
TypeError: an integer is required (got type str)
Can someone tell me how to use the super function for that?
As jasonharper specified, a class can only inherit from another class, such as socket.socket. You can't inherit from an instance of a class, as you're trying to do here. The parameters you're trying to pass to socket.socket() should go in the super().__init__().
class walkie_talkie(socket.socket):
def __init__(self):
self.BUFFERSIZE = 8192
self.STATE = None
self.IP = None # Server IP
self.PORT = 5000
self.NUMBER_OF_UNACCEPTED_CONNECTIONS = 1
self.bytestream = None
super().__init__(socket.AF_INET, socket.SOCK_STREAM)
This answer was posted as an edit to the question Python super init custom socket class by the OP V.Hunon under CC BY-SA 4.0.

Twisted UDP - Why can't I send without listening?

How do I send without calling Reactor.ListenUDP?
If I try, then I get an exception in the protocol class that the transport is NULL. It seems it doesn't get set up in the base class until you call the reactor.ListenUDP. Surely, you have the ability to send without listening for incoming messages. After all, a server might not even want to receive at all.
----main.py------
import wx
from twisted.internet import wxreactor
from main_window import MainWindow
def main():
app = wx.App(False)
frame = MainWindow(None, 'UDP Demo')
from twisted.internet import reactor
reactor.registerWxApp(app)
reactor.run()
if __name__ == "__main__":
wxreactor.install()
main()
---main_window.py---
# SNIP - Nothing really relevant. Just creates the classes below and hooks up buttons to call their methods
---plugin.py----
from enum import Enum
from twisted.internet.error import CannotListenError
from udp_protocol import UDPProtocol
class PluginBase(object):
"""
This is just a dummy class to match what is in Falco
"""
def __init__(self, app_dist, *args, **kwargs):
pass
class Plugin(PluginBase):
class State(Enum):
"""
Represents the states that the plugin can be in
"""
CLOSED = 0 # Initial state
LISTENING = 1 # After open() is called
RECV_CALLBACK_REGISTERED = 2 # After listen() is called
def __init__(self, app_dist, *args, **kwargs):
super(Plugin, self).__init__(app_dist, *args, **kwargs)
self.state = self.State.CLOSED
self.port = None
self.listener = None
self.listen_callback = None
self.protocol = UDPProtocol(self.on_data_received)
def listen(self, port, isBroadcast, callback, errback=None):
if self.state != self.State.CLOSED:
raise RuntimeError("UDP Plugin already in an opened state")
self.port = port
# Start listening
try:
from twisted.internet import reactor
self.listener = reactor.listenUDP(self.port, self.protocol)
self.state = self.State.LISTENING
callback()
except CannotListenError as err:
error_json = {"error": err[2].strerror}
if errback is not None:
errback(error_json)
def stop_listening(self):
if self.listener is not None:
self.listener.stopListening()
self.listener = None
self.listen_callback = None
self.port = None
self.state = self.State.CLOSED
def send(self, addr, port, data):
# While it seems like one could send without listening for incoming messages,
# twisted's implementation doesn't seem to work that way?
# The transport in the protocol object only gets created when we call reactor.listenUDP,
# as far as I can tell
if self.state == self.State.CLOSED:
raise RuntimeError(
"UDP Plugin must be in an open state before attempting to send")
self.protocol.send(addr, port, data)
# SNIP recv
----udp_protocol.py---
from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
class MyProtocol(DatagramProtocol):
def datagramReceived(self, data, (host, port)):
print "received %r from %s:%d" % (data, host, port)
self.transport.write(data, (host, port))
def send(self, addr, port, data):
self.transport.write(data, (addr, port))
Surely, you have the ability to send without listening for incoming messages.
As it turns out, no. However, nothing compels you to do anything with any incoming messages that arrive.

Running multiple sockets at the same time in python

I am trying to listen and send data to several sockets at the same time. When I run the program I get en error saying:
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 704, in __init__
if sock.getsockopt(SOL_SOCKET, SO_TYPE) != SOCK_STREAM:
OSError: [Errno 9] Bad file descriptor
The first socket starts up correctly, but once I try to start a new one I get the error.
class bot:
def __init__(self, host, port):
self.host = host
self.port = port
sock = socket.socket()
s = None
def connect_to_server(self):
self.s = ssl.wrap_socket(self.sock)
self.s.connect((self.host, self.port))
Above is the class and then I'm running several instances.
def run_bots(bots):
for bot in bots:
try:
threading.Thread(target=bot.connect_to_server()).start()
except:
print(bot.host)
print("Error: unable to start thread")
bots = []
b = bot('hostname.com', 1234)
b1 = bot('hostname1.com', 1234)
bots.append(b)
bots.append(b1)
run_bots(bots)
I don't know what to do. Anyone have an idea of what could be the problem?
You are using the same socket. Create one for each bot:
class bot:
def __init__(self, host, port):
self.host = host
self.port = port
self.s = None
def connect_to_server(self):
sock = socket.socket()
self.s = ssl.wrap_socket(sock)
self.s.connect((self.host, self.port))

Shutting down Python BasicHTTPServer from another thread

I have a script which sets up a BasicHTTPServer in a thread so that the main script can automatically open a web browser pointing to the server url to download a file. After the file is downloaded, I want to shut down that server but I have no clue how to go about it. This is an example of what I've done currently:
def server():
HandlerClass = SimpleHTTPRequestHandler
ServerClass = BaseHTTPServer.HTTPServer
Protocol = 'HTTP/1.0'
server_address = ('127.0.0.1', 8000)
HandlerClass.protocol_version = Protocol
httpd = ServerClass(server_address, HandlerClass)
httpd.serve_forever()
def download():
t = threading.Thread(name='server', target=server)
t.start()
webbrowser.open('safari-http://127.0.0.1:8000/')
I want to shut down the server after webbrowser.open().
Thank you
I tried the example given here. Can you check if it worked for you.
runFlag = True
def server(server_class=BaseHTTPServer.HTTPServer,
handler_class=BaseHTTPServer.BaseHTTPRequestHandler):
global runFlag
server_address = ('127.0.0.1', 8000)
HandlerClass.protocol_version = Protocol
httpd = ServerClass(server_address, HandlerClass)
while runFlag:
httpd.handle_request()
httpd.shutdown()
def download():
t = threading.Thread(name='server', target=server)
t.start()
webbrowser.open('https:\\www.google.com')
global runFlag
runFlag = False
So after digging deep through many articles I managed to find a kind of messy solution that works for me which closes the server completely. To do it I incorporated code from the following sources:
The Green Place
Corey Goldberg
UI is a module exclusive to the iOS Python IDE Pythonista which basically just creates buttons "start", "stop" and "visit" which bind to their respective _t functions. The ui.in_background decorator just lets the ui remain responsive while things happen in the background.
self.httpd.socket.close() is what really closes the server but it's messy and prints an ugly error to stdout/err so I had no choice but to suppress it by redirecting stdout/err to a dead class so the error is dropped. Standard stdout/err behaviour is restored immediately after. Thank you all for the time and effort you took to help me, I appreciate it greatly.
import console
import BaseHTTPServer
import SocketServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
import sys
import threading
import webbrowser
from time import sleep
import ui
original_stdout = sys.stdout
original_stderr = sys.stderr
class BasicServer(SocketServer.TCPServer):
allow_reuse_address = True
class NullifyOutput():
def write(self, s):
pass
class ServerThread(threading.Thread):
def __init__(self, ip, port):
super(ServerThread, self).__init__()
self.ip = ip
self.port = port
self.HandlerClass = SimpleHTTPRequestHandler
self.Protocol = 'HTTP/1.0'
self.server_address = (self.ip, self.port)
self.HandlerClass.protocol_version = self.Protocol
try:
self.httpd = BasicServer(self.server_address, self.HandlerClass)
except:
self.port += 1
self.server_address = (self.ip, self.port)
self.httpd = BasicServer(self.server_address, self.HandlerClass)
self.stoptheserver = threading.Event()
def run(self):
while not self.stoptheserver.isSet():
self.httpd.handle_request()
def join(self, timeout=None):
self.stoptheserver.set()
self.httpd.socket.close()
super(ServerThread, self).join(timeout)
server = ServerThread('127.0.0.1', 8000)
def start_t(sender):
print server.isAlive()
if not server.isAlive():
server.start()
def visit_t(sender):
webbrowser.open('http://127.0.0.1:' + str(server.port))
#webbrowser.open('safari-http://127.0.0.1' + str(server.port))
# Use the safari- prefix to open in safari. You may need to switch to
# pythonista then back to safari to get the page to load.
#ui.in_background
def stop_t(sender):
sys.stdout, sys.stderr = NullifyOutput(), NullifyOutput()
server.join(3)
sys.stdout, sys.stderr = original_stdout, original_stderr
ui.load_view('SimpleServer').present('sheet')
Here is an example from cryptoassets.core project, status server:
class StatusHTTPServer(threading.Thread):
def __init__(self, ip, port):
threading.Thread.__init__(self)
self.running = False
self.ready = False
self.ip = ip
self.port = port
def run(self):
self.running = True
self.ready = True
self.httpd.serve_forever()
self.running = False
def start(self):
server_address = (self.ip, self.port)
try:
self.httpd = HTTPServer(server_address, StatusGetHandler)
except OSError as e:
raise RuntimeError("Could not start cryptoassets helper service status server at {}:{}".format(self.ip, self.port)) from e
threading.Thread.start(self)
def stop(self):
if self.httpd and self.running:
self.httpd.shutdown()
self.httpd = None

Python TCPServer Address Reuse

import SocketServer
import sys
from Queue import *
import threading
class CustomTCPServer(SocketServer.TCPServer):
def __init__(self, server_address, RequestHandlerClass, commandQueue=Queue):
self.queue = commandQueue
SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate=False)
SocketServer.TCPServer.allow_reuse_address = True
self.server_bind()
self.server_activate()
class SingleTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
commandQueue = self.server.queue
self.data = self.request.recv(1024).strip()
try:
commandQueue.put(self.data)
except Queue.Empty:
print 'Sorry.. Cannot accept any more.. Queue is full..'
def main():
HOST = ''
PORT = 50099
commandQueue = Queue()
server = CustomTCPServer((HOST, PORT), SingleTCPHandler, commandQueue)
threadObject = threading.Thread(target=server.serve_forever)
threadObject.setDaemon(True)
threadObject.start()
threadObject.join()
if __name__ == '__main__':
main()
But whenever I run the code for second time I get the message that
socket.error: [Errno 98] Address already in use
I am confused..
Any suggestion would be appreciated..
Instead of:
SocketServer.TCPServer.allow_reuse_address = True
Which sets the value on the base class that you've already subclassed yourself from, (and created an instance of),
Use:
self.allow_reuse_address = True
It doesn't look like you're ever closing the socket at the end. Try adding a server.shutdown() (as well as changing the allow_reuse_address) to shut it down at the end after the thread join.

Categories

Resources