Python StreamRequestHandler - python

So i've got a socket server running the StreamRequestHandler class. The problem lies in writing back to the socket. MY client does not seem to receive the data.
class MyTCPHandler(SocketServer.StreamRequestHandler)
def handle(self):
while 1:
self.data = self.rfile.readline()
...process data and pref result...
self.wfile.write(result)
break
this seems straight forward, what am i missing. Is there a way to flush the send buffer, as the amount of data i send is very little?

If I understand it correctly, you have problems with sending data from the server to the client. I had the same problem. Turns out, wfile and rfile are of type BytesIO and take only binary data.
So if your result is a normal string, you'll have to make it binary.
bstring = b"your string"
bstring = bytes("normal string", "utf8")
class MyTCPHandler(SocketServer.StreamRequestHandler)
def handle(self):
while 1:
self.data = self.rfile.readline()
if not self.data:
break
self.wfile.write(b"Got some data\n")

Related

How to convert shell command via input throught socket into json serialize data. e.g: json.dumps and json.loads python 3x

I am trying to run a command remotely via socket connection but when ever I give a command code crashes with a result:
generates subprocess.CalledProcessError: Command '"dir"' returned non-zero exit status 1.
Client
!/usr/bin/env python
import socket
import subprocess
import json
class remote:
def __init__(self, ip, port):
self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.connection.connect((ip, port))
def reliable_send(self, data):
json_data = json.dumps(data)
self.connection.send(json_data)
def reliable_receive(self):
json_data = json.dumps(self.connection.recv(1024).decode())
return json.loads(json_data)
# stuck here! I am trying to create a mkdir via subprocess command. But cannot figure out after this.
def execute_system_command(self, command):
return subprocess.check_output(command, shell=True)
def run(self):
while True:
command = self.reliable_receive()
command_result = self.execute_system_command(command)
self.reliable_send(command_result)
connection.close()
my_class = remote("xxx.xxx.xxx.xxx", xxxx)
my_class.run()
Objective is to run all the command typed in the server to work in the client. But to manage the large file. Server is trying to put all the received data into Json serialization data via json.dumps and fetch via json.loads. Code works great without serialization.
Server
!/usr/bin/env python
import socket, json
class Listener:
def __init__(self, ip, port):
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listener.bind((ip, port))
listener.listen(0)
print("[+] Waiting for incoming connections")
self.connection, address = listener.accept()
print("[+] Got connection from " + str(address))
def reliable_send(self, data):
json_data = json.dumps(data)
self.connection.send(json_data)
def reliable_receive(self):
json_data = json.dumps(self.connection.recv(1024).decode())
return json.loads(json_data)
def execute_remotely(self, command):
self.reliable_send(command)
return self.reliable_receive()
def run(self):
while True:
command = raw_input(">> ")
result = self.execute_remotely(command)
print(result)
my_listener = Listener("xxx.xxx.xxx.xxx", xxxx)
my_listener.run()
In reliable_receive, you’re calling json.loads immediately on the result of calling json.dumps. That’s obviously pointless.
In particular, you already called json.dumps in reliable_send. More generally, you of course need the same number of dumps and loads; the imbalance produced the extra quotes evident in the error message.
The more fundamental issue is that your protocol is unreliable: it assumes that messages arrive atomically and separately (never guaranteed by SOCK_STREAM, as suggested by the name) and are no longer than 1024 B. You need to use some form of incremental parsing to recognize the ends of messages.
This could be as simple as appending a null byte to each, since we know that JSON never uses one. But you still have to receive in a loop until you see one, remove it, and keep any tail past it for the next command.

Asynchronously send data over multiple sockets in Python

I am trying to wrap my head around asynchronous code in Python. I have been reading about coroutines and async/await statements but at the end of the day, I am still a little lost. I thought I would do this through an example:
I have different servers listening on different ports at different destinations. I'd like to execute the following function asynchronously (as in to send data to all of them at the same time, since they would be I/O bound).
def send_current_elements(current_list):
for msg in current_list:
data, destination = msg
ip, port = (destination['ip'], destination['port'])
socket = PIRSocket()
socket.connect((ip,port))
if type(data).__name__ == 'str':
data = data.encode()
s.sendall(data)
s.close()
Adding an async doesn't seem to do the trick:
async def send_current_elements(current_list):
for msg in current_list:
data, destination = msg
ip, port = (destination['ip'], destination['port'])
socket = PIRSocket()
socket.connect((ip,port))
if type(data).__name__ == 'str':
data = data.encode()
socket.sendall(data)
socket.close()
Help would be much appreciated to help me understand this.
Also, PIRSocket is just a wrapper around a normal socket which prepends the message with its length before sending.

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.

Python socket send doesn't send the whole string

I am having trouble when I try to send a string from client to server over LAN
code for client:
def p():
os.system('tasklist > p.txt')
f = open('p.txt', 'r+')
proc = '''
'''
for line in f:
proc+=(line+'\b')
c.send(proc)
code for server:
def main():
while True:
command = raw_input('COMMAND >> ')
s.sendall(command)
data = s.recv(4096)
print(data+'\n\n')
and I am recieving only part of the data I sent.
I've already tried setting more bytes on s.recv, but that didn't really help, the problem persists.
What seems to be the problem?
Ref the docs https://docs.python.org/2/library/socket.html#socket.socket.send "Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data."
Check the return value from c.send(proc) for the total bytes sent and send more if needed.
E.g. if you are sending 100 chars, and c.send(data) returns 40, then you need to call c.send(data[40:]), and so on.
Alternatively, you might be able to/want to use sendall: https://docs.python.org/2/library/socket.html#socket.socket.sendall

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.

Categories