I'm trying to start a UDP server in python 3.
I copied the code from this example.
This is my exact code.
import socketserver
class MyUDPHandler(socketserver.BaseRequestHandler):
"""
This class works similar to the TCP handler class, except that
self.request consists of a pair of data and client socket, and since
there is no connection the client address must be given explicitly
when sending data back via sendto().
"""
def handle(self):
data = self.request[0].strip()
socket = self.request[1]
print("{} wrote:".format(self.client_address[0]))
print(data)
if __name__ == "__main__":
HOST, PORT = "localhost", 19446
with socketserver.UDPServer((HOST, PORT), MyUDPHandler) as server:
server.serve_forever()
I have only removed the reply from the handle method and changed the port number.
when i try to run it i get this
$ sudo python3 test.py
File "test.py", line 19, in <module>
with socketserver.UDPServer((HOST, PORT), MyUDPHandler) as server:
AttributeError: __exit__
I am attempting to run this in Python 3.4.2 installed on a Raspberry Pi 3, it was working this morning.
I googled AttributeError: __exit__ and found that with uses built in methods such as __exit__ to gracefully close after it has finished running instructions indented after it.
The exact same code runs fine on my windows machine (Python 3.6.2) and the code used to run on my raspberry pi and the only thing i have done with it all day was install x11vnc server and plugged in a lot of USB devices. (A capture card and arduinos, no usb drives from untrusted sources).
So my question is, what can cause an Attribute Error: __exit__ in the socketserver library.
context manager was added to socketserver in 3.6: https://bugs.python.org/issue26404, with commit.
below 3.6, in 3.4.2, you have to call server_close() manually:
try:
server = socketserver.UDPServer((HOST, PORT), MyUDPHandler)
server.serve_forever()
finally:
server.server_close()
Related
So I'm studying Python from the book Fundamentals of Python by Kenneth Lambert and I'm having trouble with an error from one of the programs in the book.
Here in chapter 10 talks about Clients and Servers. My professor asked us to key those programs in Python to see how they work. The first programs worked perfectly, but in a program I'm getting an error which seems to be a Windows error instead of a Python one.
This is the program in page 339:
from socket import *
from time import ctime
from threading import Thread
class ClientHandler(Thread):
"""Handles a client request."""
def __init__(self, client):
Thread.__init__(self)
self._client = client
def run(self):
self._client.send(bytes(ctime() + '\nHave a nice day!' , 'ascii'))
self._client.close()
HOST = "localhost"
PORT = 5000
BUFSIZE = 1024
ADDRESS = (HOST, PORT)
server = socket(AF_INET, SOCK_STREAM)
server.bind(ADDRESS)
server.listen(5)
# The server now just waits for connections from clients
# and hands sockets off to client handlers
while True:
print('Waiting for connection')
client, address = server.accept()
print('...connected from:', address)
handler = ClientHandler(client)
handler.start()
When I run this program, it displays the "Waiting for connection" message in the Shell. However, when I try to connect to the program using the Command Prompt, it displays the following error:
C:\Python33>python multi-client-server.py
Traceback (most recent call last):
File "multi-client-server.py", line 30, in <module>
server.bind(ADDRESS)
OSError: [WinError 10048] Only one usage of each socket address (protocol/networ
k address/port) is normally permitted
We haven't studied this in class a lot. So I'm just wondering why this happens and how to fix it.
Thanks!
So, as per your questions:
We haven't studied this in class a lot. So I'm just wondering why this
happens and how to fix it.
Why:
You are trying to run the same code snippet from two different CMD on a Windows OS. So, when you initially execute the code snippet, the server starts listening on the port number 5000, then when you execute the same code snippet from the second CMD wndow it conflicts with the socket that is already being used by the first one.
I tested this on Windows 8.
How to fix:
To fix this issue, you have to simply use a different port number when you execute the code snippet for the second time, so that the socket(IP+port) doesn't conflicts with the previous one. Simply edit your code and put PORT = 15200 and save this file with a different name.(I have provided the code below too.) Now try executing the first code snippet file from a CMD windows and then execute the second code snippet file that you created right now from the second CMD window. The issue will be solved!
Code:
from socket import *
from time import ctime
from threading import Thread
class ClientHandler(Thread):
"""Handles a client request."""
def __init__(self, client):
Thread.__init__(self)
self._client = client
def run(self):
self._client.send(bytes(ctime() + '\nHave a nice day!' , 'ascii'))
self._client.close()
HOST = "localhost"
PORT = 15200 # Port number was changed here
BUFSIZE = 1024
ADDRESS = (HOST, PORT)
server = socket(AF_INET, SOCK_STREAM)
server.bind(ADDRESS)
server.listen(5)
# The server now just waits for connections from clients
# and hands sockets off to client handlers
while True:
print('Waiting for connection')
client, address = server.accept()
print('...connected from:', address)
handler = ClientHandler(client)
handler.start()
If you prefer then have a look here for the basic client-server issues.
So I'm studying Python from the book Fundamentals of Python by Kenneth Lambert and I'm having trouble with an error from one of the programs in the book.
Here in chapter 10 talks about Clients and Servers. My professor asked us to key those programs in Python to see how they work. The first programs worked perfectly, but in a program I'm getting an error which seems to be a Windows error instead of a Python one.
This is the program in page 339:
from socket import *
from time import ctime
from threading import Thread
class ClientHandler(Thread):
"""Handles a client request."""
def __init__(self, client):
Thread.__init__(self)
self._client = client
def run(self):
self._client.send(bytes(ctime() + '\nHave a nice day!' , 'ascii'))
self._client.close()
HOST = "localhost"
PORT = 5000
BUFSIZE = 1024
ADDRESS = (HOST, PORT)
server = socket(AF_INET, SOCK_STREAM)
server.bind(ADDRESS)
server.listen(5)
# The server now just waits for connections from clients
# and hands sockets off to client handlers
while True:
print('Waiting for connection')
client, address = server.accept()
print('...connected from:', address)
handler = ClientHandler(client)
handler.start()
When I run this program, it displays the "Waiting for connection" message in the Shell. However, when I try to connect to the program using the Command Prompt, it displays the following error:
C:\Python33>python multi-client-server.py
Traceback (most recent call last):
File "multi-client-server.py", line 30, in <module>
server.bind(ADDRESS)
OSError: [WinError 10048] Only one usage of each socket address (protocol/networ
k address/port) is normally permitted
We haven't studied this in class a lot. So I'm just wondering why this happens and how to fix it.
Thanks!
So, as per your questions:
We haven't studied this in class a lot. So I'm just wondering why this
happens and how to fix it.
Why:
You are trying to run the same code snippet from two different CMD on a Windows OS. So, when you initially execute the code snippet, the server starts listening on the port number 5000, then when you execute the same code snippet from the second CMD wndow it conflicts with the socket that is already being used by the first one.
I tested this on Windows 8.
How to fix:
To fix this issue, you have to simply use a different port number when you execute the code snippet for the second time, so that the socket(IP+port) doesn't conflicts with the previous one. Simply edit your code and put PORT = 15200 and save this file with a different name.(I have provided the code below too.) Now try executing the first code snippet file from a CMD windows and then execute the second code snippet file that you created right now from the second CMD window. The issue will be solved!
Code:
from socket import *
from time import ctime
from threading import Thread
class ClientHandler(Thread):
"""Handles a client request."""
def __init__(self, client):
Thread.__init__(self)
self._client = client
def run(self):
self._client.send(bytes(ctime() + '\nHave a nice day!' , 'ascii'))
self._client.close()
HOST = "localhost"
PORT = 15200 # Port number was changed here
BUFSIZE = 1024
ADDRESS = (HOST, PORT)
server = socket(AF_INET, SOCK_STREAM)
server.bind(ADDRESS)
server.listen(5)
# The server now just waits for connections from clients
# and hands sockets off to client handlers
while True:
print('Waiting for connection')
client, address = server.accept()
print('...connected from:', address)
handler = ClientHandler(client)
handler.start()
If you prefer then have a look here for the basic client-server issues.
Help to build python ForkingTCPServer. This server returns an error when client connects to the server. When I use ThreadingTCPServer instead of ForkingTCPServer it works fine. socketFileIO module contains functions for pickle to/from socket:
http://code.activestate.com/recipes/577667-pickle-tofrom-socket/
server.py:
import SocketServer, time
from socketFileIO import write, read
class MyClientHandler(SocketServer.BaseRequestHandler):
def handle(self):
print self.client_address
data=read(self.request)
print 'Client:', data
time.sleep(10) # for testing
write(self.request,data)
self.request.close()
HOST, PORT = '', 50007
server = SocketServer.ForkingTCPServer((HOST, PORT), MyClientHandler)
server.serve_forever()
client.py:
import socket
from socketFileIO import write, read
HOST = '127.0.0.1'
PORT = 50007
data=["A","B","C","End"]
for x in data:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
write(s,x)
y=read(s)
print 'Server:', y
s.close()
Error:
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 1469)
Traceback (most recent call last):
File "c:\Python26\lib\SocketServer.py", line 283, in _handle_request_noblock
self.process_request(request, client_address)
File "c:\Python26\lib\SocketServer.py", line 525, in process_request
pid = os.fork()
AttributeError: 'module' object has no attribute 'fork'
----------------------------------------
I have a several other questions:
How to shutdown the server by sending data "End" from client ?
How to restrict the number of connections (for example no more then 5) ?
Your fork question was already answered in comments.
For "how to shut down the server": in a similar application (but much older Python version and using xmlrpc), I used a loop invoking one request at a time until a "stop" variable was set. This appears to be supported directly in Python 2.7 now: in your threaded server, call shutdown() on the server instance, from one of the request-handler threads. (Not sure if this is available in 2.6, I de-installed my old 2.6 version a couple of months ago.) I.e.:
class MyClientHandler(SocketServer.BaseRequestHandler):
def handle(self):
...
# if we're supposed to shut down the server, do that
if somecond:
self.server.shutdown()
For limiting the number of connections: there's nothing built-in that I can see, but if you redefined the process_request handler you could count the number of active threads and wait for one to finish if there are "too many" outstanding (or work it however else you like). See the ThreadingMixIn class in SocketServer.py and compare it to the max_children code in ForkingMixIn.
I am trying to create a tcplistener in python (using pexpect if necessary) to listen for tcp connection from Ubuntu in virtualbox on a windows xp host. I would really appreciate it, if one of you could point me in the right direction. Thank you.
P.S: I have limited experience in the area, any help would be welcome.
Python already has a simple socket server provided in the standard library, which is aptly named SocketServer. If all you want is a basic listener, check out this example straight from the documentation:
import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
"""
The RequestHandler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print "%s wrote:" % self.client_address[0]
print self.data
# just send back the same data, but upper-cased
self.request.send(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
# Create the server, binding to localhost on port 9999
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()
I'm teaching myself Python networking, and I recalled that back when I was teaching myself threading, I came across this page, so I copied the scripts, updated them for Python 3.1.1 and ran them. They worked perfectly.
Then I made a few modifications. My goal is to do something simple:
The client pickles an integer and sends it to the server.
The server receives the pickled integer, unpickles it, doubles it, then pickles it and sends it back to the client.
The client receives the pickled (and doubled) integer, unpickles it, and outputs it.
Here's the server:
import pickle
import socket
import threading
class ClientThread(threading.Thread):
def __init__(self, channel, details):
self.channel = channel
self.details = details
threading.Thread.__init__ ( self )
def run(self):
print('Received connection:', self.details[0])
request = self.channel.recv(1024)
response = pickle.dumps(pickle.loads(request) * 2)
self.channel.send(response)
self.channel.close()
print('Closed connection:', self.details [ 0 ])
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('', 2727))
server.listen(5)
while True:
channel, details = server.accept()
ClientThread(channel, details).start()
And here is the client:
import pickle
import socket
import threading
class ConnectionThread(threading.Thread):
def run(self):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('localhost', 2727))
for x in range(10):
client.send(pickle.dumps(x))
print('Sent:',str(x))
print('Received:',repr(pickle.loads(client.recv(1024))))
client.close()
for x in range(5):
ConnectionThread().start()
The server runs fine, and when I run the client it successfully connects and starts sending integers and receiving them back doubled as expected. However, very quickly it exceptions out:
Exception in thread Thread-2:
Traceback (most recent call last):
File "C:\Python30\lib\threading.py", line 507, in _bootstrap_inner
self.run()
File "C:\Users\Imagist\Desktop\server\client.py", line 13, in run
print('Received:',repr(pickle.loads(client.recv(1024))))
socket.error: [Errno 10053] An established connection was aborted by the softwar
e in your host machine
The server continues to run and receives connections just fine; only the client crashes. What's causing this?
EDIT: I got the client working with the following code:
import pickle
import socket
import threading
class ConnectionThread(threading.Thread):
def run(self):
for x in range(10):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('localhost', 2727))
client.send(pickle.dumps(x))
print('Sent:',str(x))
print('Received:',repr(pickle.loads(client.recv(1024))))
client.close()
for x in range(5):
ConnectionThread().start()
However, I still don't understand what's going on. Isn't this just opening and closing the socket a bunch of times? Shouldn't there be time limitations to that (you shouldn't be able to open a socket so soon after closing it)?
Your client is now correct - you want to open the socket send the data, receive the reply and then close the socket.
The error original error was caused by the server closing the socket after it sent the first response which caused the client to receive a connection closed message when it tried to send the second message on the same connection.
However, I still don't understand
what's going on. Isn't this just
opening and closing the socket a bunch
of times?
Yes. This is acceptable, if not the highest performance way of doing things.
Shouldn't there be time
limitations to that (you shouldn't be
able to open a socket so soon after
closing it)?
You can open a client socket as quickly as you like as every time you open a socket you will get a new local port number, meaning that the connections won't interfere. In the server code above, it will start a new thread for each incoming connection.
There are 4 parts to every IP connection (source_address, source_port, destination_address, destination_port) and this quad (as it is known) must change for ever connection. Everything except source_port is fixed for a client socket so that is what the OS changes for you.
Opening server sockets is more troublesome - if you want to open a new server socket quickly, your
server.bind(('', 2727))
Above then you need to read up on SO_REUSEADDR.