The Client and Server can successfully connect however only one command can be issued. Been at this for a while and wanted some outside help, any feedback or suggested improvements would be great thanks in advance.
Been looking at other posts which suggest I may have prematurely closed the connection but I don't believe this to be true due to the fact the program doesn't throw any disconnection errors though I may be wrong.
client.py
import socket
import sys
import os
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
##server = input("Enter server IP: ")
##print(server)
##
##port = int(input("Enter port: "))
##print(port)
def send_msg(msg):
sock.sendall(msg.encode())
def get_msg():
msg = sock.recv(2048).decode()
return msg
server = "127.0.0.1"
port = 100
sock.connect((server, port))
print("Connecting to " + server + " on port " + str(port) + "\n")
while True:
#Send data
msg = input(os.getcwd() + "> ")
print("Sending '" + msg + "'")
send_msg(msg)
#Response
#amnt_exp = len(msg)
#data = sock.recv(2048)
data = get_msg()
if data == "exit":
print("\nClosing connection")
sock.close()
else:
print("Received: \n" + data)
server.py
import socket
import sys
import os
import subprocess
#Create a TCP/IP Socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
##server = input("Enter server IP: ")
##print(server)
##
##port = int(input("Enter port: "))
##print(port)
def send_msg(msg):
conn.sendall(msg.encode())
def get_msg():
msg = conn.recv(2048).decode()
return msg
server = "127.0.0.1"
port = 100
#Config
sock.bind((server, port))
print("Bound to " + server + " on port " + str(port) + "\n")
sock.listen(1)
print("Waiting for a connection...")
while True:
conn, caddr = sock.accept()
print("Connected!\n")
print("Waiting for a command...")
#data = conn.recv(2048).decode()
data = get_msg()
#Exit
if data == "exit":
print("\nConnection closed")
conn.close()
print("Received '" + data + "'")
#Command Exec
call = subprocess.Popen(data, stdout = subprocess.PIPE, shell=True)
#Output
output, err = call.communicate()
call_status = call.wait()
#print("Output: ", output)
#print("Exit status: ", call_status)
#Reply
msg = "Command successful\n" + "Output: " + str(output) + "\n" + "Exit status:" + str(call_status)
print("Sending reply...")
print("\nWaiting for a command...")
send_msg(msg)
The problem is that your server loop only accepts a single command, and then it goes back to accept a whole new connection, and never looks at the old connection again.
Your output is pretty misleading, because it does print out Waiting for a command.... But that's only happening because you have an extra print("\nWaiting for a command...") before send_msg, and you don't have any output before sock.accept. You can see what's actually happening if you make your prints accurate. For example:
sock.listen(1)
while True:
print('Waiting for a connection...') # inside the loop, not before it
conn, caddr = sock.accept()
# ... etc. ...
print("Sending reply...")
# Don't print Waiting for a command here, because you aren't
send_msg(msg)
# And print something after the send succeeds
print("Sent")
print()
So, now you know what's wrong, how do you fix it?
Simple. We just need a nested loop. Once you accept a client connection, keep using that connection until they exit:
sock.listen(1)
while True:
print('Waiting for a connection...') # inside the loop, not before it
conn, caddr = sock.accept()
print("Connected!\n")
while True:
print("Waiting for a command...")
data = get_msg()
#Exit
if data == "exit":
print("\nConnection closed")
conn.close()
break # go back to the outer accept loop to get the next connection
print("Received '" + data + "'")
# ... etc. ...
print()
Related
I'm working on a project that requires me to make a Python reverse listener that can send commands to a client that connects to my server, below is my server code and i am stuck on how to get multiple connections from more than just one client at the same time.
thank you
#!/usr/bin/python3
import socket
import sys
import time
import threading
from queue import Queue
NUMBER_OF_THREADS = 2
JOB_NUMBER = [1, 2]
queue = Queue)
all_connections = []
all_addresses = []
# create socket
def socket_create():
try:
global host
global port
global s
host = '0.0.0.0'
port = 5555
s = socket.socket()
except socket.error as msg:
print("Socket creation error: " + str(msg))
# bind socket to port and wait for connection from client
def socket_bind():
try:
global host
global port
global s
print("Binding socket to port: " + str(port))
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(5)
except socket.error as msg:
print("Socket binding error: " + str(msg))
time.sleep(5)
socket_bind()
# accept connections from multiple clients and save to list
def accept_connections():
for c in all_connections:
c.close()
del all_connections[:]
del all_addresses[:]
while 1:
try:
conn, address = s.accept()
conn.setblocking(1)
all_connections.append(conn)
all_addresses.append(address)
print("\nConnection has been established: " + address[0])
except:
print("Error accepting connections")
# interactive prompt
def start_luka():
while True:
cmd = input('luka> ')
if cmd == 'list':
list_connections()
elif 'select' in cmd:
conn = get_target(cmd)
if conn is not None:
send_target_commands(conn)
else:
print("Command not recognized")
# displays all current connections
def list_connections():
results = ''
for i, conn in enumerate(all_connections):
try:
conn.send(str.encode(' '))
conn.recv(20480)
except:
del all_connections[i]
del all_addresses[i]
continue
results += str(i) + ' ' + str(all_addresses[i][0]) + ' ' + str(all_addresses[i][1]) + '\n'
print('------ Clients -----' + '\n' + results)
def main():
socket_create()
socket_bind()
start_luka()
list_connections()
accept_connections()
main()
when i run this code it doesn't say the connection is established and it doesn't add the connection to the list i created.
and lastly i'm trying to make all of this automated, as in, the second a client connects to my server listener, these commands will automatically run (ls, pwd, IP a...ect) and a file would be created to store all the data so i can check it out later. not sure where to start on that.
thanks for helping
I have used Python socket in ESP as a server and Laptop as a client. I customized the socket codes from this site. When I send the loop as the client input, I enter a loop on the server. I don't know how the while loop is broken when I send a word other than loop, For example "Hello".
server.py:
import socket
host = ''
port = 5560
def setupServer():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket created.")
try:
s.bind((host, port))
except socket.error as msg:
print(msg)
print("Socket bind comlete.")
return s
def setupConnection():
s.listen(1)
conn, address = s.accept()
print("Connected to: " + address[0] + ":" + str(address[1]))
return conn
def Hello_():
print('Hello')
def Loop_():
while True:
print('yes')
def dataTransfer(conn):
while True:
data = conn.recv(1024)
data = data.decode('utf-8')
dataMessage = data.split(' ', 1)
command = dataMessage[0]
if command == 'loop':
Loop_()
if command == 'Hello':
Hello_()
else:
print("X")
conn.close()
s = setupServer()
while True:
try:
conn = setupConnection()
dataTransfer(conn)
except:
break
client.py
import socket
host = '192.168.56.1'
port = 5560
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
while True:
command = input("Enter your command: ")
s.send(str.encode(command))
s.close()
I know your time is valuable and I appreciate your attention for spending time for help me.
If you want the Loop_() method to return when more data is received on the socket, you can modify the method so that it calls select() to poll the socket to see if more data has arrived, as shown below. (Note that I've added a conn argument to the Loop_() method so I can pass in the socket to check it)
import select
[...]
def Loop_(conn):
while True:
print('yes')
inReady, outReady, exReady = select.select([conn], [], [], 0.0)
if (conn in inReady):
print('more data has arrived at the TCP socket, returning from Loop_()')
break
def dataTransfer(conn):
while True:
data = conn.recv(1024)
data = data.decode('utf-8')
dataMessage = data.split(' ', 1)
command = dataMessage[0]
if command == 'loop':
Loop_(conn)
if command == 'Hello':
Hello_()
else:
print("X")
conn.close()
i have a client will send some string to my server. However, i need to send twice so that the server get the package. So for every package client wants to send the server, it needs to send twice. I do not understand why it went in this way.
my server's code that does listening:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
myIp = "0x2A"
myPort = 2222
targetPort = 0
myAddress = ("localhost",myPort)
bufferSize = 1024
def listen():
print('starting up on {} port {}'.format(*myAddress))
sock.bind(myAddress)
# sock.listen(1)
print("waiting for message")
# connection, client_address = sock.accept()
while True:
received = sock.recvfrom(bufferSize)[0]
address = sock.recvfrom(bufferSize)[1]
received = json.loads(received.decode())
source = received.get("source")
destination = received.get("destination")
length = received.get("length")
message = received.get("message")
protocol = received.get("protocol")
print("the source is: " + source)
if destination == myIp:
print("the message is: " + message)
print('sending back to sender...')
sock.sendto(message.encode(),address)
if protocol == 0:
print("protocol is: " + str(protocol))
elif protocol == 1:
print("protocol is: " + str(protocol))
print("write data to log file....")
f = open("log.txt","w")
f.write(message)
print('done!')
elif protocol == 2:
print("protocol is: " + str(protocol))
# sock.close()
print("exit")
sock.close()
sys.exit()
else:
print("this is not my package: \n" + "destination Ip is: " + destination + "\n my Ip is: " + myIp)
if not received:
break
my client's code that does the sending:
def send():
try:
sock.sendto(message.encode(),serverAddress)
print("message: " + message + " is sent")
finally:
print('closing socket')
sock.close()
received = sock.recvfrom(bufferSize)[0]
address = sock.recvfrom(bufferSize)[1]
The first recvfrom will do the first read. The second recvfrom will do another read. Voila: you need two reads. Instead you should do a single read:
received, address = socket.recvfrom(bufferSize)
https://iperf.fr/iperf-doc.php
https://iperf.fr/
//server.py
import socket
import select
import sys
from thread import *
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if len(sys.argv) != 3:
print "Correct usage: script, IP address, port number"
exit()
IP_address = str(sys.argv[1])
Port = int(sys.argv[2])
server.bind((IP_address, Port))
server.listen(100)
list_of_clients = []
def clientthread(conn, addr):
conn.send("Welcome to this chatroom!")
while True:
try:
message = conn.recv(2048)
if message:
print "<" + addr[0] + "> " + message
message_to_send = "<" + addr[0] + "> " + message
broadcast(message_to_send, conn)
else:
remove(conn)
except:
continue
def broadcast(message, connection):
for clients in list_of_clients:
if clients!=connection:
try:
clients.send(message)
except:
clients.close()
remove(clients)
def remove(connection):
if connection in list_of_clients:
list_of_clients.remove(connection)
while True:
conn, addr = server.accept()
list_of_clients.append(conn)
print addr[0] + " connected"
start_new_thread(clientthread,(conn,addr))
conn.close()
server.close()
The client side script will simply attempt to access the server socket created at the specified IP address and port. Once it connects, it will continuously check as to whether the input comes from the server or from the client, and accordingly redirects output. If the input is from the server, it displays the message on the terminal. If the input is from the user, it sends the message that the users enters to the server for it to be broadcasted to other users.
//client.py
import socket
import select
import sys
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if len(sys.argv) != 3:
print "Correct usage: script, IP address, port number"
exit()
IP_address = str(sys.argv[1])
Port = int(sys.argv[2])
server.connect((IP_address, Port))
while True:
sockets_list = [sys.stdin, server]
read_sockets,write_socket, error_socket = select.select(sockets_list,[],[])
for socks in read_sockets:
if socks == server:
message = socks.recv(2048)
print message
else:
message = sys.stdin.readline()
server.send(message)
sys.stdout.write("<You>")
sys.stdout.write(message)
sys.stdout.flush()
server.close()
attempting message encryption with a basic client to host connection
client code:
import socket
import datetime
import time
import threading
tLock = threading.Lock()
shutdown = False
def receving(name, sock):
while not shutdown:
try:
tLock.acquire()
while True:
data, addr = socket.recvfrom(1024)
print (str(data))
except:
pass
finally:
tLock.release()
host = '127.0.0.1'
port = 0
server = ('127.0.0.1',5000)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
s.setblocking(0)
rT = threading.Thread(target=receving, args=("RecvThread",s))
rT.start()
alias = input("Name: ")
IP=int(socket.gethostbyname(socket.gethostname()).replace(".","5"))
time=(int(datetime.datetime.now().strftime("%Y%m%d%H%M%S")))
qw=(int(str((time)+(IP))))
a=int("934")
b=int("346")
c=int("926")
d=int("9522")
e=int("7334")
f=int("5856")
g=int("2432")
h=int("2027")
i=int("7024")
j=int("828")
k=int("798")
m=int("593")
n=int("662")
l=int("5950")
o=int("357")
p=int("506")
q=int("237")
r=int("98")
s=int("372")
t=int("636")
u=int("553")
v=int("255")
w=int("298")
x=int("8822")
y=int("458")
z=int("657")
space=("633")
msg=input("")
msg=msg.replace("a",(str(a)))
msg=msg.replace("b",(str(b)))
msg=msg.replace("c",(str(c)))
msg=msg.replace("d",(str(d)))
msg=msg.replace("e",(str(e)))
msg=msg.replace("f",(str(f)))
msg=msg.replace("g",(str(g)))
msg=msg.replace("h",(str(h)))
msg=msg.replace("i",(str(i)))
msg=msg.replace("j",(str(j)))
msg=msg.replace("k",(str(k)))
msg=msg.replace("m",(str(m)))
msg=msg.replace("n",(str(n)))
msg=msg.replace("l",(str(l)))
msg=msg.replace("o",(str(o)))
msg=msg.replace("p",(str(p)))
msg=msg.replace("q",(str(q)))
msg=msg.replace("r",(str(r)))
msg=msg.replace("s",(str(s)))
msg=msg.replace("t",(str(t)))
msg=msg.replace("u",(str(u)))
msg=msg.replace("v",(str(v)))
msg=msg.replace("w",(str(w)))
msg=msg.replace("x",(str(x)))
msg=msg.replace("y",(str(y)))
msg=msg.replace("z",(str(z)))
msg=msg.replace(" ",(str(space)))
print(msg)
msg=int(msg)
msg=int(msg)*(qw)
print(msg)
fileb=open("key.txt","w")
filec=fileb.write(str(qw))
fileb.close()
file=open("msg decrypt.txt","w")
filea=file.write(str(msg))
file.close()
msg=(str(e)(msg))
print(IP)
print(qw)
if msg != 'q':
if msg != '':
s.sendto(alias.encode() + ": ".encode() + (str(msg).encode)(), server)
tLock.acquire()
msg = input(alias + "-> ")
tLock.release()
shudown = True
rT.join()
s.close()
host code:
import socket
import time
host = '127.0.0.1'
port = 5000
clients = []
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host,port))
s.setblocking(0)
quitting = False
print ("Server Started.")
while not quitting:
try:
data, addr = s.recvfrom(1024)
if "Quit" in str(data):
quitting = True
if addr not in clients:
clients.append(addr)
print (time.ctime(time.time()) + str(addr) + ": :" + str(data))
for client in clients:
s.sendto(data, client)
except:
pass
s.close()
Im struggling as my poor excuse of a encryption is mostly numbers so therefore when im sending using the sendto function only uses str`s or so I think?
either way I get the error:
Traceback (most recent call last):
File "H:\client 2.py", line 103, in <module>
msg=(str(e)(msg))
TypeError: 'str' object is not callable
If msg is an index you should write :
msg = str(e)[msg]