All of the below mentioned is on windows machines using python 2.7
Hello,
I am currently attempting to listen on a socket for data send by a remote program. This data is then printed to the screen and user input is requested that is then returned to remote program. In testing I have been able to have the remote program send me a menu of command line programs (cmd, ipconfig, whoami, ftp) and then my program returns with a number as a selection of the menu option.
The remote program receives my response and sends the output of the selected command. ipconfig and whoami work perfectly, but cmd and ftp only returns the output of the terminal once. (I.E. I can enter one command into the FTP program and send that too the remote program before I never hear back)
The part of my code that fails is that
if ready[0]: never becomes ready a second time after the first conversation.
I know the remote program is functioning correctly as I can use netcat to act in lieu of my code and operate the cmd terminal indefinitely.
How do I go about properly implementing a python socket listener that can account for this type of connection?
My "program" in its entirety:
import socket, sys, struct, time, select
host = ''
port = 50000
connectionSevered=0
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print 'Failed to create socket'
sys.exit()
print '[+] Listening for connections on port '+str(port)+'.'
s.bind((host,port))
s.listen(5)
def recvall(the_socket,timeout=2):
global connectionSevered
data=''; # Data found by recv
total_data=[]; # Finally list of everything
s.setblocking(0) #make socket non blocking
begin=time.time() #beginning time
while 1:
ready = select.select([client], [], [], .2)
if time.time()-begin > timeout:
print 'Timeout reached'
#Leave loop, timer has reached its threshold
break
if ready[0]:
print 'In ready loop!'
try:
data = client.recv(4096) #attempt to fetch data
if data:
begin=time.time() #reset timeout timer
total_data.append(data)
data='';
except socket.error:
print '[+] Lost connection to client. Printing buffer...'
connectionSevered=1 # Let main loop know connection has errored
pass
time.sleep(1)
#join all parts to make final string
return ''.join(total_data)
client, address = s.accept()
print '[+] Client connected!'
while (connectionSevered==0): # While connection hasn't errored
print "connectionSevered="+str(connectionSevered) # DEBUG
recvall(s)
response = raw_input() #take user input
client.sendto(response) #send input
client.close(0)
Please let me know if you need more information, any help would be greatly appreciated, I am very new to this and eager to learn.
Playing around with this for a while finally got it working nice with a telnet session locally using python 2.7.
What it does is it sets up a thread that runs when the client connects listening for client stuff.
When the client sends a return ("\r\n" might have to change that if your interacting with a Linux system?) the message gets printed to the server, while this is happening if there is a raw input at the server side this will get sent to the client:
import socket
import threading
host = ''
port = 50000
connectionSevered=0
class client(threading.Thread):
def __init__(self, conn):
super(client, self).__init__()
self.conn = conn
self.data = ""
def run(self):
while True:
self.data = self.data + self.conn.recv(1024)
if self.data.endswith(u"\r\n"):
print self.data
self.data = ""
def send_msg(self,msg):
self.conn.send(msg)
def close(self):
self.conn.close()
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(5)
except socket.error:
print 'Failed to create socket'
sys.exit()
print '[+] Listening for connections on port: {0}'.format(port)
conn, address = s.accept()
c = client(conn)
c.start()
print '[+] Client connected: {0}'.format(address[0])
c.send_msg(u"\r\n")
print "connectionSevered:{0}".format(connectionSevered)
while (connectionSevered==0):
try:
response = raw_input()
c.send_msg(response + u"\r\n")
except:
c.close()
The above answer will not work for more than a single connection. I have updated it by adding another thread for taking connections. It it now possible to have more than a single user connect.
import socket
import threading
import sys
host = ''
port = 50000
class client(threading.Thread):
def __init__(self, conn):
super(client, self).__init__()
self.conn = conn
self.data = ""
def run(self):
while True:
self.data = self.data + self.conn.recv(1024)
if self.data.endswith(u"\r\n"):
print self.data
self.data = ""
def send_msg(self,msg):
self.conn.send(msg)
def close(self):
self.conn.close()
class connectionThread(threading.Thread):
def __init__(self, host, port):
super(connectionThread, self).__init__()
try:
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.bind((host,port))
self.s.listen(5)
except socket.error:
print 'Failed to create socket'
sys.exit()
self.clients = []
def run(self):
while True:
conn, address = self.s.accept()
c = client(conn)
c.start()
c.send_msg(u"\r\n")
self.clients.append(c)
print '[+] Client connected: {0}'.format(address[0])
def main():
get_conns = connectionThread(host, port)
get_conns.start()
while True:
try:
response = raw_input()
for c in get_conns.clients:
c.send_msg(response + u"\r\n")
except KeyboardInterrupt:
sys.exit()
if __name__ == '__main__':
main()
Clients are not able to see what other clients say, messages from the server will be sent to all clients. I will leave that as an exercise for the reader.
If you're in Python 3 by now and still wondering about sockets, here's a basic way of using them:
server.py
import time
import socket
# creating a socket object
s = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
# get local Host machine name
host = socket.gethostname() # or just use (host == '')
port = 9999
# bind to pot
s.bind((host, port))
# Que up to 5 requests
s.listen(5)
while True:
# establish connection
clientSocket, addr = s.accept()
print("got a connection from %s" % str(addr))
currentTime = time.ctime(time.time()) + "\r\n"
clientSocket.send(currentTime.encode('ascii'))
clientSocket.close()
client.py
import socket
# creates socket object
s = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
host = socket.gethostname() # or just use (host = '')
port = 9999
s.connect((host, port))
tm = s.recv(1024) # msg can only be 1024 bytes long
s.close()
print("the time we got from the server is %s" % tm.decode('ascii'))
Run server.py first, then run client.py.
This is just send and receive the currentTime.
What's new in Python 3.4 sockets?
A major difference between python 2.7 sockets and python 3.4 sockets is the sending messages. you have to .encode() (usually using 'ascii' or blank as parameters/arguments)
and then using .decode()
For example use .encode() to send, and use .decode() to receive.
Extra info: client/server socket tutorial
Related
I'm trying to send console commands from one machine to another using Python sockets. I want the server to send back the results of the command to the client. If the client types "ls" I want the server to send back the results of running that command. Instead of the expected result, the server just says "action completed: ls". How can I fix this so the server will run the expect commands and return the result?
Server:
import socket
from subprocess import call
def main():
host = '127.0.0.1'
port = 5000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
c, addr = s.accept()
print('Connection established: ' + str(addr))
while True:
try:
data = c.recv(1024).decode('utf-8')
print('sending data: ' + data)
c.send(data.encode('utf-8'))
if data == 'q':
break
except NameError:
error = 'Command does not exist'
c.send(error.encode('utf-8'))
continue
except SyntaxError:
error = 'Command does not exist'
c.send(error.encode('utf-8'))
continue
c.close()
Client:
import socket
from subprocess import call
def main():
host = '127.0.0.1'
port = 5000
s = socket.socket()
s.connect((host, port))
message = str(input('> '))
while message != 'q':
try:
s.send(message.encode('utf-8'))
data = s.recv(1024).decode('utf-8')
print('Action completed: %s' % data)
message = str(input('> '))
except NameError:
print("Command not recognized.")
continue
except SyntaxError:
print("Command not recognized")
continue
I recently built a socket connection in order to communicate with an android device.
I decided to use UDP instead of TCP (which is what you did). For UDP as well as TCP you need a sender and a receiver on both sides of the communication.
The port number that is received in the "addr" variable changes with every connection, so you cannot use it.
What I did, I assigned two different ports one for sending from A to B and the other port to send from B to A.
Here is my server code:
import socket # socket connection
import threading # Multithreading
import time # Timeing
# ----------------------------------------------
# Variables
# ----------------------------------------------
UDPListen2Port = 12345
UDPSend2Port = 123456
Listen2IP = '' # input your local IP here
# ----------------------------------------------
# Threading class
# ----------------------------------------------
class signalProcessingThread(threading.Thread):
def __init__(self, iP, cmdIn):
threading.Thread.__init__(self)
self.iP = iP
self.cmdIn = cmdIn
def run(self):
print("Recv--", self.iP ,"--", self.cmdIn) # Display Thread Info
cmdOut = self.EvalMessage() # Actual signal processing
byteOut = bytes(cmdOut.encode("utf-8")) # Convert Server reply to bytes
sock.sendto(byteOut,(self.iP,UDPSend2Port)) # Send Server Reply to Socket
# ----------------------------------------------
# Initialize Socket
# ----------------------------------------------
sock = socket(AF_INET, SOCK_DGRAM) # -- UDP -- connection
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # in case the port was not properly closed before
sock.bind((Listen2IP,UDPListen2Port)) # bind to the port
# ----------------------------------------------
# Listen to Socket
# ----------------------------------------------
while True:
try: # wait for a connection
data,addr = sock.recvfrom(66507) # number of bytes in the message
msg = data.decode('utf-8')
newThread = signalProcessingThread(addr[0],msg)
newThread.start()
except KeyboardInterrupt:
print('Connection failed')
sock.close()
sock.close()
The client code is quite similar, with the difference that it doesn't necessarily need to run in a thread. Hope I could help.
Hello I tried to make a simple server that accept multiple clients simultaneously I'm new to python and I have a difficult to understand it....I try to change my code in multi-thread applications but without positive result...here is the code:
import socket, threading
def message():
while 1:
data = connection.recv(1024)
if not data: break
#connection.sendall(b'-- Message Received --\n')
print(data.decode('utf-8'))
connection.close()
def connection():
address = input("Insert server ip")
port = 44444
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((address, port))
s.listen(1)
print("Server started! Waiting for connections...")
def accept connection():
connection, address = s.accept()
print('Client connected with address:', address)
t=thread.Threading(target=message,args=(connection))
t.run()
I know that there are many errors but I'm new in python sorry :(
The original non-threaded code is:
import socket
address = input("Insert server ip:")
port = 44444
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((address, port))
s.listen(1)
print("Server started! Waiting for connections...")
connection, address = s.accept()
print('Client connected with address:', address)
while 1:
data = connection.recv(1024)
if not data: break
#connection.sendall(b'-- Message Received --\n')
print(data.decode('utf-8'))
connection.close()
Your basic design is close, but you've got a whole lot of little problems making it hard to move forward.
First, you have a function name with a space in it, which isn't allowed. And you have an IndentationError because you didn't indent its contents.
Next, inside that accept_connection function, you're using threading wrong.
thread.Threading doesn't exist; you probably meant threading.Thread.
args has to be a sequence (tuple, list, etc.) of values. You probably expected (connection) to be a tuple of one value, but it's not; tuples are defined by commas, not parentheses, and what you have is just the value connection with superfluous parentheses around it. You wanted (connection,) here.
Also, calling run on a thread object just runs the thread's code in the current thread. You want to call start, which will start a new thread and call the run method on that thread.
Meanwhile, you're never actually calling this function anywhere, so of course it can't do anything. Think about where you want to call it. After creating the listener socket, you want to loop around accept, kicking off a new client thread for each accepted connection, right? So, you want to call it in a loop, either inside connection, or at the top level (in which case connection has to return s).
And finally, your accept_connection function can't access local variables from some other function; if you want it to use a socket named s, you have to pass it as a parameter.
So:
def connection():
address = input("Insert server ip")
port = 44444
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((address, port))
s.listen(1)
print("Server started! Waiting for connections...")
while True:
accept_connection(s)
def accept_connection(s):
connection, address = s.accept()
print('Client connected with address:', address)
t=thread.Threading(target=message, args=(connection,))
t.start()
As a side note, be careful with using sock.recv(1024) and assuming you're going to get the whole message that the other side sent with send(msg). You might get that, or you might get half the message, or the whole message plus half of another message the client sent later. Sockets are just streams of bytes, like files, not streams of separate messages; you need some kind of protocol to separate messages.
The simplest possible protocol is to send each message on its own line. Then you can just do socket.makefile() and for line in f:, just like you would for a real file. Of course this doesn't work if your messages can have newlines, but you can, e.g., backslash-escape them on one side and unescape them on the other.
This is a pretty old post but there's a nice way to do what you're talking about. Here's a link to an example I posted a little while back:
https://bitbucket.org/matthewwachter/tcp_threadedserver/src/master/
And the script:
from datetime import datetime
from json import loads, dumps
from pprint import pprint
import socket
from threading import Thread
class ThreadedServer(Thread):
def __init__(self, host, port, timeout=60, debug=False):
self.host = host
self.port = port
self.timeout = timeout
self.debug = debug
Thread.__init__(self)
# run by the Thread object
def run(self):
if self.debug:
print(datetime.now())
print('SERVER Starting...', '\n')
self.listen()
def listen(self):
# create an instance of socket
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# bind the socket to its host and port
self.sock.bind((self.host, self.port))
if self.debug:
print(datetime.now())
print('SERVER Socket Bound', self.host, self.port, '\n')
# start listening for a client
self.sock.listen(5)
if self.debug:
print(datetime.now())
print('SERVER Listening...', '\n')
while True:
# get the client object and address
client, address = self.sock.accept()
# set a timeout
client.settimeout(self.timeout)
if self.debug:
print(datetime.now())
print('CLIENT Connected:', client, '\n')
# start a thread to listen to the client
Thread(target = self.listenToClient,args = (client,address)).start()
# send the client a connection message
# res = {
# 'cmd': 'connected',
# }
# response = dumps(res)
# client.send(response.encode('utf-8'))
def listenToClient(self, client, address):
# set a buffer size ( could be 2048 or 4096 / power of 2 )
size = 1024
while True:
try:
# try to receive data from the client
data = client.recv(size).decode('utf-8')
if data:
data = loads(data.rstrip('\0'))
if self.debug:
print(datetime.now())
print('CLIENT Data Received', client)
print('Data:')
pprint(data, width=1)
print('\n')
#send a response back to the client
res = {
'cmd': data['cmd'],
'data': data['data']
}
response = dumps(res)
client.send(response.encode('utf-8'))
else:
raise error('Client disconnected')
except:
if self.debug:
print(datetime.now())
print('CLIENT Disconnected:', client, '\n')
client.close()
return False
if __name__ == "__main__":
ThreadedServer('127.0.0.1', 8008, timeout=86400, debug=True).start()
Here is some example code I have showing a threaded socket connection.
def sock_connection( sock, host ):
"Handle socket"
pass
while 1:
try:
newsock = sock.accept()
thread = Thread( target=sock_connection, args=newsock )
thread.start()
except Exception, e:
print "error on socket connection: " % e)
I have overridden the handle function. Right now, every time a client connects, it will keep the socket open to echo what the client sent in all caps. The server should not allow more than one connection, thus only one socket is kept open. How would this be done?
Server -
import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
while 1:
self.data = self.request.recv(1024).strip()
print self.data
# echo back data in all caps
self.request.sendall(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = SocketServer.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
The client needs to do work with the server for some amount of time (10 seconds in this example). The server should not accept connections from any other client during this time.
Client -
import socket
import sys
import time
HOST, PORT = "localhost", 9999
data = 1
future = time.time() + 10 # work for 10 seconds
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# Connect to server and send data
sock.connect((HOST, PORT))
except socket.error:
sys.exit()
else:
while time.time() < future:
sock.sendall(data + "\n")
received = sock.recv(1024)
print received
data += 1
finally:
sock.close()
Your handle will never quit, and because you did not use any multithreading/multiprocessing, it will serve one connection forever. So first you should have some way to quit. Such as a message "quit" from the client side. Like this:
def handle(self):
while 1:
self.data = self.request.recv(1024).strip()
print self.data
if self.data == 'quit':
break
# echo back data in all caps
self.request.sendall(self.data.upper())
I am creating a Python Server/Client chat program (like AOL instant messenger) using sockets.
I run into a problem when I force quit the server or the client because my socketInstance.recv() method is sent a huge amount of "" blank strings. I am wondering how to run a closing method, like a deconstructor, when the cmd window is force quit so I can exit gracefully.
I've included my code, just in case (shouldn't be necessary tho):
Echo server program
import socket
import sys
import time
HOST = '' # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#s = socket.socket() # Create a socket object
HOST = socket.gethostname() # Get local machine name
print "Socket hostname: ", HOST
s.bind((HOST, PORT))
conn = None
def check_for_messages():
print 'Check for messages...'
global conn
while 1:
try:
data = conn.recv(1024)
if not data: break
conn.sendall(data)
print data
except socket.error:
#[Errno 10054] Client Closes
pass
print "END OF CHECK MESS"
def check_for_client():
print 'Listening...'
global conn
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
check_for_client()
check_for_messages()
Echo client program
import threading
import socket
import time
PORT = 50007 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = socket.gethostname() # The local host
s.connect((HOST, PORT))
getUserInputThread = None
getMessThread = None
receivedMessages = []
def getMessage():
print "getMessageThread running"
while 1:
data = s.recv(1024)
if not data:
print "OVERLORD: Possible server disconnect"
break
receivedMessages.append(data)
print "getMessageThread ending\n"
def getUserInput():
print "getUserInputThread running"
while 1:
message = raw_input("type: ")
s.sendall(message)
#print messages in list:
while len(receivedMessages) > 0:
print "Received Messages Length: %d" % len(receivedMessages)
print receivedMessages.pop(0)
print "getUserInputThread ending"
getUserInputThread = threading.Thread(target=getUserInput)
getUserInputThread.start()
getMessThread = threading.Thread(target=getMessage)
getMessThread.start()
Thanks,
Jordan
You could use the atexit module to perform final cleanup before terminating:
import atexit
#atexit.register
def do_cleanup():
print "doing some cleanup..."
#close sockets, put chairs on tables, etc
print "goodbye"
#loop forever, until the user hits ctrl-c
while True:
pass
Result:
C:\Users\kevin\Desktop>test.py
Traceback (most recent call last):
File "C:\Users\kevin\Desktop\test.py", line 12, in <module>
while True:
KeyboardInterrupt
doing some cleanup...
goodbye
This will work if your user force quits with a KeyboardInterrupt, but not if he closes the command window with the X button, terminates the task with task manager, unplugs the computer, etc.
Alright, I've spent about three hours fiddling with socket programming in Python trying to make a simple chat program. I've gotten the client to send text to the server and then, from then client, it repeats the message to it's self. However, I want the message to be sent to the server and then the server, not the client, re-send it to all client's connected. I'm having issues doing this. This is my code so far:
Server Side Code:
import SocketServer
def handle(self):
data = self.request[0].strip()
socket = self.request[1]
print "%s wrote:" % self.client_address[0]
print data
socket.sendto(data.upper(), self.client_address)
if __name__ == "__main__":
HOST, PORT = "localhost", 25555
server = SocketServer.UDPServer((HOST, PORT), MyUDPHandler)
server.serve_forever()
Client Side Code:
import socket
import sys
global HOST
global PORT
HOST, PORT = "localhost", 25555
while 1 > 0:
data = raw_input(">".join(sys.argv[1:]))
# SOCK_DGRAM is the socket type to use for UDP sockets
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# As you can see, there is no connect() call; UDP has no connections.
# Instead, data is directly sent to the recipient via sendto().
sock.sendto(data + "\n", (HOST, PORT))
received = sock.recv(1024)
print "Sent: %s" % data
print "Received: %s" % received
Right now your app is instantiating the MyUDPHandler class for each client connection. When the connection is opened you need to store that instance to a static array or queue. Then when the handle() call is made it can loop through all those sockets and send a copy of the data to each of them.
I'd checkout the python documentation; it basically does what your looking to: http://docs.python.org/library/socketserver.html#asynchronous-mixins
And what I'd change from that example (Don't just drop this in; it probably has glaring bugs!):
handlerList = []
class ...
def handle(self):
handlerList.append(self)
while (1):
data = self.request.recv(1024)
if (not data):
break
cur_thread = threading.currentThread()
response = "%s: %s" % (cur_thread.getName(), data)
for x in handlerList:
x.request.send(response)
psudo_code_remove_self_from_handlerList()
Would you like to play with a server that echos packets to all sockets but the original source of the data?
import socket, select
def main():
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('', 8989))
server.listen(5)
sockets = [server]
while True:
for sender in select.select(sockets, [], [])[0]:
if sender is server:
sockets.append(server.accept()[0])
else:
try:
message = sender.recv(4096)
except socket.error:
message = None
if message:
for receiver in sockets:
if receiver not in (server, sender):
receiver.sendall(message)
else:
sender.shutdown(socket.SHUT_RDWR)
sender.close()
sockets.remove(sender)
if __name__ == '__main__':
main()