Python sockets + select - python

i use this function to run my Server via Sockets:
def run(self):
# The 'main' function
print 'Running ... '
Running = True
while Running:
InList,OutList,ExceptList = select.select(self.Connections,[],[])
for Connection in InList:
if Connection == self.Server:
# Server got a new connecting Client
User, Adress = self.Server.accept() # New User Connection
Data = {'User':User,'Adress':Adress}
self.Connections.append(Data) # Store the new User Connection
print 'User ', Data, ' connected'
else:
# Some other Socket got data for the Server
Data = Connection.recv(1024)
if not Data:
print 'No new Data!'
break
print Data
However when sending data i am getting this Error: TypeError: argument must be an int, or have a fileno() method, on line 23 which is the select() line.
Looking up the manual and those examples (http://code.activestate.com/recipes/531824-chat-server-client-using-selectselect/ and http://ilab.cs.byu.edu/python/select/echoserver.html) i see no difference and dont understand why i wouldn't work. self.Connections contains only the Server socket and when using print self.Connections it gives me:
[<socket._socketobject object at 0x020B6BC8>]
stating, that it's a list i am passing to select() which should be correct.
What am i doing wrong? Thanks!

The first time select.select runs, there's no problem, because self.Connections contains only a socket object, which is perfectly valid.
In the second trip through the while loop, however, self.Connections has picked up another element: the Data dictionary constructed in the if Connection == self.Server: block. That dictionary is not an integer, and it doesn't have a fileno method, so select.select complains when it sees it.

Related

Cant receive data from socket

I'm making a client-server program, and there is problem with client part.
Problem is in infinite receiving data. I've tested this particular class, listed below, in a python interpreter. I've succesfuly(maybe not) connected to google, but then program stoped in function recvData() in data = self.socket.recv(1024)
class client():
def __init__(self, host, port):
self.host = host
self.port = port
self.socket = self.connect()
self.command = commands()
def connect(self):
'''
Connect to a remote host.
'''
try:
import socket
return socket.create_connection((self.host, self.port))
except socket.error:
print(":: Failed to connect to a remote port : ")
def sendCommand(self, comm):
'''
Send command to remote host
Returns server output
'''
comman = comm.encode()
# for case in switch(comman):
# if case(self.command.RETRV_FILES_LIST.encode()):
# self.socket.send(b'1')
# return self.recvData()
# if case():
# print(":: Got wrong command")
if (comman == b'1'):
self.socket.send(b'1')
return self.recvData()
def recvData(self):
'''
Receives all the data
'''
i = 0
total_data = []
while(True):
data = self.socket.recv(1024)
if not data: break
total_data.append(data)
i += 1
if i > 9:
break
return total_data
about commented part :
I thought problem in Case realization, so used just if-then statement. But it's not.
Your problem is that self.socket.recv(1024) only returns an empty string when the socket has been shut down on the server side and all data has been received. The way you coded your client, it has no idea that the full message has been received and waits for more. How you deal with the problem depends very much on the protocol used by the server.
Consider a web server. It sends a line-delimited header including a content-length parameter telling the client exactly how many bytes it should read. The client scans for newlines until the header is complete and then uses that value to do recv(exact_size) (if large, it can read chunks instead) so that the recv won't block when the last byte comes in.
Even then, there a decisions to make. The client knows how large the web page is but may want to send a partial data to the caller so it can start painting the page before all the data is received. Of course, the caller needs to know that is what happens - there is a protocol or set of rules for the API itself.
You need to define how the client knows a message is complete and what exactly it passes back to its caller. A great way to deal with the problem is to let some other protocol such as [zeromq](http://zeromq.org/ do the work for you. A simple python client / server can be implemented with xmlrpc. And there are many other ways.
You said you are implementing a client/server program then you mentioned "connected to google" and telnet... These are all very different things and a single client strategy won't work with all of them.

How to check the python socket recvfrom() data

I am working on socket programming in python. Using ESP python i have created a socket to server and sending a request (in API packet format, according to server code it will respond). In receiving socket, i need to check the data(if data is received, it need continue to next operation. If not, i need to send request once again).
sending is okay. In receiving socket, if it is not receiving data, it is not going to next instruction.. please help me out.
code:
try:
s = socket(AF_INET, SOCK_DGRAM)
print "socket created"
except socket.error:
print "failed to create socket"
sys.exit()
sending data:
s.sendto("packet of data", 0, (HOST,PORT))
In receiving:
recvpack, payload=s.recvfrom(1024)
if not recvpack:
s.sendto("packet of data", 0, (HOST,PORT))
elif(recvpack[]="packet of data"):
pass # continue to next operations..
In the above receiving statement, if recvfrom() in not getting anydata, how to check recvpack and get back to next operations.. If socket.settimeout() or socket.setblocking() is the solution, how to use these..
If you don't mind a blocking call, I usually use settimeout to wait for a message. settimeout will raise an exception if it doesn't receive a message in time.
So basically you could do something like this:
s.settimeout(1)
try:
recvpack, payload = s.recvfrom(1024)
except error:
recvpack = None
if recvpack is not None:
...
Source : https://docs.python.org/2/library/socket.html#socket.socket.settimeout

List appending during loop seems to be optimized out in python?

I have a client-server application, with the client gathering some information, and having it json serialized and sent to the server, who will later store it in a database. In the server's tcp serving module, I have code that loads json objects from strings in a list and then appends them to another list like this (look at the loop inside bind_and_listen, which begins with for client in clients):
""" TCP Server before the main database. """
import socket
import sys
import logging
import json
import structs.client_data as cl_data
import db.register as register
cursor = register.cursor
client_list = []
domain_list = []
# connection constants
HOST = None
PORT = None
def config_server(host, port):
""" Configure the server's address and port. """
if not host:
logging.warning("HOST not supplied in the configuration file.")
sys.exit(-1)
if not port:
logging.warning("PORT not supplied in the configuration file.")
sys.exit(-1)
global HOST
global PORT
HOST = host
PORT = int(port)
def handle_files_question(request):
""" Read the file policy from the database for the server that sent it.
Params:
#request: The request as sent from the server.
"""
index = request.find(':')
hostname = request[index + 1:]
return register.query_file_policy(hostname)
def handle_size_question(request):
""" Read the size policy from the database for the server that sent it.
Params:
#request: The request as sent from the server.
"""
index = request.find(':')
hostname = request[index + 1:]
return register.query_size_policy(hostname)
def bind_and_listen():
""" Bind the server to the socket, and listen for incoming connections. """
serv = None
# create the socket
try:
serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, v:
message = "Failed to create a socket: Message is {} and error code is {}"
errno, errormsg = v # is a (errno, message) tuple
message = message.format(errormsg, errno)
logging.error(message)
print message
sys.exit(-1)
# bind out socket to the address
try:
serv.bind((HOST, PORT)) # the double parens are to create a tuple with one element
except socket.error, msg:
message = "Binding of the socket failed. Error Code : {} Message: {}."
message = message.format(msg[0], msg[1])
logging.error(message)
print message
sys.exit(-2)
serv.listen(5) # 5 is the maximum number of queued connections we will allow
logging.info("Server is now listening on port %d" % (PORT,))
# we have the try block here only to facilitate the finally block
# that follows, so that we can reliably close the database everytime
# we have to close the program, but we don't have an exception raised
# everytime a client disconnects, the db is closed, and the networking
# module attempts to use the cursor of the expired connection.
try:
while True:
conn, addr = serv.accept()
hostname = None
output = str()
# this is the code handling the first policy question, regarding files
# 256 bytes should be enough to specify the question and hostname
res = conn.recv(256)
output = res
if output.startswith('files'):
files = handle_files_question(output)
conn.send(str(files))
# reset the output string
output = str()
# repeat the above procedure for the size policy question
res = conn.recv(256)
output = res
if output.startswith('size'):
size = handle_size_question(output)
conn.send(str(size))
# reset the output string
output = str()
# handle the rest of the data that the client sends
# (mainly, the clients and domains lists)
while True:
res = conn.recv(1024)
if not res:
break
output += res
# at this point, we assume that we have the full output string
# so we will split it to a list of strings representing the json
# representation of our clients
output = output.split('---')
domains_index = output.index('Domains_list')
clients = output[0:domains_index - 1] # -1 to compensate for a newline in the list
print clients
domains = output[domains_index + 1:-1]
hostname = output[0].split()[1]
clients = clients[2:-1] # ignoring the hostname and the Clients_list delimiter
for client in clients:
jason = json.loads(client)
client = cl_data.Client(jason['client_id'], jason['login'], jason['pname'], jason['email'])
client.files = jason['files']
client.size = jason['size']
client.size_human = jason['size_human']
client.domains = jason['domains']
client.domain_num = jason['domain_num']
client_list.append(client)
# the code below seems to prevent the problem?
#for client in client_list:
# print client.pname
for domain in domains:
jason = json.loads(domain)
domain = cl_data.DomainName(jason['domain_id'], jason['name'], jason['client_id'])
domain_list.append(domain)
conn.close()
register.update_clients(hostname, client_list)
register.update_domains(hostname, domain_list)
logging.info("Connection from %s is terminated." % (addr,))
except KeyboardInterrupt:
message = "\nCtrl + C was pressed, and an interruption signal has been registered."
message += " Terminating the server now."
logging.info(message)
print message
finally:
register.close_connection()
All well and good at this point. After I am finished with the loop I use the client_list to update an SQL database with this code:
register.update_clients(hostname, client_list)
The thing is, if I add something like print len(client_list) before the above code, I am getting 1 as a result, unless I do something like:
for client in client_list:
print client.email
in which case, I get the list with the whole number of objects that should be in it (about 180 or so).
From the above, I am gathering that the list appending gets optimized out for some reason that I can not comprehend, unless I force the list to be iterated immediately after the first loop has ended. Does anyone else have any insight on this? Is this standard behavior and I am doing something wrong? Is this a bug or something?
This is python 2.7.9 on debian 8 (jessie) according to the interpreter and /etc/os-release.
(I know I could use the dis module to investigate it further, but the way the module is written presents me with some ImportErrors when I try to import it to a python interpreter)

Python Sockets - Using Coordinates getPos

Basically trying to use client to send coordinates of a character on the screen and then broadcast that to the other client so it draws the character on the screen.
Yet i'm getting the following errors:
Client Side: s.send((y))
Server Side: ValueError: invalid literal for long() with base 10
Client Code that i get error on:
def updatecoords(task):
s.send(name)
print 'Name sent...'
def updatepos(task):
y = format(Cat.getPos())
s.send((y))
print 'Position sent'
return Task.cont
def readServer(task):
try:
data = s.recv(1024)
print data
except:
print 'no data received'
return Task.cont
Server Code that i get error on:
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((HOST,PORT))
server_socket.listen(1)
conn, addr = server_socket.accept()
print('Someone connected.He :%s%addr')
while True:
data = conn.recv(1024)
if not data:
break
data = pickle.loads(data) # Or json.loads(data)
print "Got id: {message_id}, data: {message}".format(**data)
You are trying to unpickle the received data:
data = pickle.loads(data)
But you are not pickling the data before sending it:
y = format(Cat.getPos())
s.send((y))
Also you have to decide which serialization protocol you wan't to use because pickle and json are not compatible and this comment:
# Or json.loads(data)
suggests that you think both pickle and json should be able to deserialize received data.
So instead of using format you should make your client function similar to this:
def updatepos(task):
y = pickle.dumps(Cat.getPos())
s.sendall(y)
print 'Position sent'
But still this server code:
data = pickle.loads(data)
print "Got id: {message_id}, data: {message}".format(**data)
will work only under two conditions:
- class Cat is imported on server side, otherwise pickle.loads will throw UnpicklingError since pickle protocol preserves class name and unpickling restores the object of class Cat but it can't be done if definition of this class is unavailable
- Cat.getPos() returns a dict (or dict-like object) with keys message_id and message, otherwise format(**data) will throw ValueError if data can't be used as dict or KeyError if one of the mentioned keys is missing in dict
You should also notice that I've replaced s.send((y)) with s.sendall(y) since the first one doesn't guarantee that all data will be sent as documentation says https://docs.python.org/2/library/socket.html#socket.socket.send
I've also dropped additional brackets around y - this doesn't change anything but they are not needed.
As you have posted only part of your code, I was only able to resolve issues present in the posted code sample.

What is the difference between a conn and a channel in socket programming

I am currently coding my first basic socket server, and I have stumbled upon two different forms for the server to communicate with the client - threads (which I think use conn in python) and channels, which I don't really understand - but they seem like another way to communicate between the client and server. What is the difference between the two and how are they best used?
Here is the code as asked for - please pardon my N00biness:)
CONN/THREADS
def clientthread(conn):
#Sending message to connected client
#This only takes strings (words)
conn.send("Welcome to the server. Type something and hit enter\n")
#loop so that function does not terminate and the thread does not end
while True:
#Receiving from client
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
print data
#To close the connection
conn.close()
while True:
#Wait to accept a connection - blocking call
conn, addr = s.accept()
#display client information (IP address)
print 'Connected with ' + addr[0] + ':' + str(addr[1])
#Start new thread takees 1st argument as a function name to be run, second
#is the tuple of arguments to the function
start_new_thread(clientthread ,(conn,))
CHANNELS
while True:
#Wait to accept a connection - blocking call
channel, details = s.accept()
#display client information (IP address)
print 'Connected with ', details
#Start new thread takees 1st argument as a function name to be run, second
#is the tuple of arguments to the function
#Sending message to connected client
#This only takes strings (words)
intro = "Welcome to the server. Type something and hit enter"
print channel.recv(len(intro))
channel.send(intro)
#loop so that function does not terminate and the thread does not end
while True:
#Receiving from client
data = channel.recv(1024)
if not data:
break
channel.sendall(data)
print data
They do exactly the same thing, except one uses channel and the other uses conn.

Categories