I created a server code to establish connection between multiple clients. When a client connected, a new thread will start to identify the client number. However when a client left, the thread number should reduce by 1 as it indicates the client number has reduced, but unfortunately, i encountered some problems in reducing thread number.
Here is my server code:
My thread number = ThreadCount
import socket
import os
from _thread import *
ServerSocket = socket.socket()
host = ''
port = 1233
ThreadCount = 0
try:
ServerSocket.bind((host, port))
except socket.error as e:
print(str(e))
print('Waitiing for a Connection..')
ServerSocket.listen(5)
def threaded_client(connection):
connection.send(str.encode('Welcome to the Server\n'))
ClientNo = " You are Client:" + str(ThreadCount)
connection.sendall(str.encode(ClientNo))
while True:
data = connection.recv(2048)
data1 = data.decode('utf-8')
reply = 'Server Says: ' + data1
if (data1 == "exit"):
print("One Client is left" + str(ThreadCount))
break
connection.sendall(str.encode(reply))
connection.close()
while True:
Client, address = ServerSocket.accept()
start_new_thread(threaded_client, (Client,))
ThreadCount += 1
print('Connected to: ' + address[0] + ':' + str(address[1]) + " | Thread: " + str(ThreadCount) + " | Client: " + str(ThreadCount))
ServerSocket.close()
This is the response: When the client left, the threadcount still the same as 2.
As I try to reduce the threadcount, it shows error like this:
How can solve this issue?
Thank you
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 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)
So I have a simple Client-Server.
They properly connect with command line arguments, send and receiving data.
When the server isn't up and running but the client executes: Attempt to connect, after 1 second display message that it timed out (3 times) before closing.
the closest i can come to it, is simply attempting it 3 times.
import sys
from socket import *
# Get the server hostname, port and data length as command line arguments
argv = sys.argv
host = argv[1]
port = argv[2]
count = argv[3]
# Command line argument is a string, change the port and count into integer
port = int(port)
count = int(count)
data = 'X' * count # Initialize data to be sent
# Create UDP client socket. Note the use of SOCK_DGRAM
clientsocket = socket(AF_INET, SOCK_DGRAM)
# Sending data to server
# times out after 1 second (?)
for i in range(3):
try:
print("Sending data to " + host + ", " + str(port) + ": " + data)
clientsocket.sendto(data.encode(),(host, port))
# Receive the server response
dataEcho, address = clientsocket.recvfrom(count)
# Display the server response as an output
print("Receive data from " + address[0] + ", " + str(address[1]) + ": " + dataEcho.decode())
break
except:
print("timed out")
finally:
#Close the client socket
clientsocket.close()
How would I add a timer to it? Just adding 1 second between each attempt instead of how I coded.
If you just want the program to sleep for x seconds you could import time, and then add time.sleep(num_of_seconds_to_sleep) after your clientsocket.close() line.
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()
I'm building a tcp/ip server in python that works with clients.
Each client gets its own thread and its socket is added to a list called client_list.
there also is a variable "clients_connected" which stores the amount of connected clients.
for some reason it just works with one client at the moment.
Also when a client disconnects, it should be removed from client_list but I'm not sure how to do that.
Could you take a look at the code please? thanks a lot!
this thread is looking for incoming connections:
def addclientsthread(sock):
global client_list
conn, addr = sock.accept()
client_list += [conn]
print_line('Client connected on ' + addr[0] + "\n")
start_new_thread(clientthread, (conn,))
So when a client connects it gets its own "clientthread"
def clientthread(conn):
# handling connections.
global clients_connected
while True:
# Receiving from client
in_data = conn.recv(1024)
data = decrypt(in_data)
if data.lower().find("id=-1") != -1:
clients_connected += 1
print_line("new client ID set to " + str(clients_connected) + "\n")
crypted_msg = encrypt("SID=" + str(clients_connected))
conn.sendall(crypted_msg)
pass
elif data.lower().find("uin") == 0:
uin_id = int(data[4:])
clients_connected -= 1
break
else:
print_line(data)
if not data:
break
# If client disconnects
conn.close()
Oh and please don't hate, I just started coding :)
EDIT: This is the main code (not in a thread)
HOST = ''
PORT = 8820
clients_connected = 0
client_list = []
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('Socket created')
# Bind socket to host and port
try:
s.bind((HOST, PORT))
except socket.error, msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
print 'Socket successfully binded'
# Start listening on socket
s.listen(100000)
print 'Socket is listening'
start_new_thread(addclientsthread, (s,))