tcp client goes into an infinite loop in python - python

I'm trying to send a file from server to client and then get another command from client to execute and go on the program, not close the connection. But when the file transmission is done, client doesn't get commands anymore. I really don't know what's the problem. I've tried everything that pops into my mind.
This is a piece of server side code, after connecting server to socket and connecting client to server this happens :
connected = True
while(connected):
print("\nWaiting for client input ...")
message = conn.recv(1024).decode('utf-8')
message = message.split(" ")
if(message[0] == "get"):
get(message[1], conn)
and this is function get():
file = open(f"server/{name}.txt", "rb")
file_size = os.path.getsize(f"server/{name}.txt")
buffer_size = 10
counter = 1
send_bytes = file.read(buffer_size)
conn.send(send_bytes)
while ((buffer_size * counter) < file_size) :
file.seek(counter * buffer_size)
send_bytes = file.read(buffer_size)
conn.send(send_bytes)
counter = counter + 1
for the client side i have this :
while True:
message = input("ftp > ")
client.send(message.encode('utf-8'))
message = message.split(" ")
if message[0] == "get":
get(message[1])
and get function :
file = open(f"{name}.txt", "ab")
while True:
recieve_bytes = client.recv(10)
if not recieve_bytes:
break
file.write(recieve_bytes)
file.close()
print("file received.")
it has to stop the connection after this, because no more data is being transferred, but out of nowhere client commands doesn't work anymore, until i manually close the server.

Related

Decrypt message with XOR and respond over a socket

I am attempting to complete a challenge that states:
We've noticed that the aliens are sending messages between their ships, we think they're using XOR to encrypt the messages, and we've intercepted a key.
Set up a server listening on ("localhost", 10000) to intercept one of the alien messages. When you do perform a bitwise XOR on the message with the key "attackthehumans" and then respond with the encrypted data.
Tip: Read the response to get the flag.
After some research, I was able to come up with the following code. However, when I run it in the challenge's code editor, the only feedback I receive is "Error trying to connect to your server and recieving message back."
import socket
# Function to xor strings
def xor_string(string):
key = "attackthehumans"
bit_key = ''.join(format(ord(i), 'b') for i in key)
bit_data = ''.join(format(ord(i), 'b') for i in string)
xor_string = str(0)
for i in range(len(bit_key)):
if bit_data[i] == bit_key[i]:
xor_string = xor_string + str(0)
else:
xor_string = xor_string + str(1)
return xor_string
# Sets up server on localhost and port 10000
print("Setting up server...")
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("localhost", 10000))
print("Server set up. Listening for connections...")
server.listen()
conn, addr = server.accept()
print("Connected by: {}".format(addr))
# Once connection is established, server receives data, XOR's it, sends it back, and
# waits for response to get the flag.
with conn:
print("Receiving data from connection... ")
data = conn.recv()
data = data.decode()
print("Data received: {}".format(data.decode()))
xor_data = xor_string(data)
conn.sendall(xor_data.encode())
response = conn.recv()
response = response.decode()
print(response)
I am not sure what I'm doing wrong. I can't figure out if it's the socket or the xor_string function. Any help would be appreciated.
This should be enough to do your XORing:
def xor_string(string):
key = b"attackthehumans"
key = key * (len(string)//len(key)+1)
res = bytes([k^s for (k,s) in zip(key,string)])
return res
Then your main code becomes:
print("Receiving data from connection... ")
data = conn.recv()
print("Data received:", data)
xor_data = xor_string(data)
conn.sendall(xor_data)
print(conn.recv())

How to disconnect client from socket server without server crshing?

I am making a server using Python 3.7. The objective of it is to have multiple people connect to it (currently one client for testing) and send data back and forth. The data being sent is a user's high score in my game. I want the server to get the data, compare the data to the highest score, and then send the data back and have the computer save it to a file. The thing is though, the client receives the text data as 0's and 1's! And when you exit the game and try to reconnect the server crashes with:
BrokenPipeError: [Errno 32] Broken pipe
Here is the code for the server:
import socket
import sys
import time
servsock = socket.socket()
host = '192.168.158.155'
port = 5555
highest_score = '0'
servsock.bind((host, port))
print('Sucsessful bind')
servsock.listen(1)
conn, addr = servsock.accept()
print(addr, 'Has connected')
receiving = conn.recv(1024)
receiving = receiving.decode()
while True:
if receiving > highest_score:
highest_score = receiving
message = highest_score
message = message.encode()
conn.send(message)
else:
highest_score = highest_score
failed = highest_score
failed = failed.encode()
conn.send(failed)
Here is the code for the game client:
# Read high score
with open('high_score/high_score.txt', 'r+') as f:
score_contents = f.read().replace("\n", " ")
f.close()
# Send data to server
lsock = socket.socket()
host = '192.168.158.155'
port = 5555
lsock.connect((host, port))
print('Connected')
ready_message = score_contents
ready_message = ready_message.encode()
lsock.send(ready_message)
print('sent')
new_high_score = lsock.recv(1024)
new_high_score = new_high_score.decode()
print(str(new_high_score))
with open('high_score/GLOBALhigh_score.txt', 'r+') as GLOBALf:
GLOBALf.truncate()
GLOBALscore_contents = GLOBALf.write(f'Highest Score:,{new_high_score}')
GLOBALf.close()
Any help is greatly appreciated!
The real root of your problem is that the accept was not in the loop, but here's how to use integers instead of strings. Note that your if statement was always sending the actual high score, so there's no need to duplicate that code>
import socket
import sys
import time
servsock = socket.socket()
host = 'localhost'
port = 5555
highest_score = 0
servsock.bind((host, port))
print('Sucsessful bind')
servsock.listen(1)
while True:
conn, addr = servsock.accept()
print(addr, 'Has connected')
receiving = int(conn.recv(1024))
if receiving > highest_score:
highest_score = receiving
message = str(highest_score).encode()
conn.send(message)
One other thing, when you're sending the score from the client, you convert the newline to space. Don't do that; just send digits. And you don't need "r+" permission if you're just going to read, and you don't need "r+" permission if you're just going to write. Use "w" for that and skip the truncate call.
# Read high score
with open('high_score/high_score.txt', 'r') as f:
score_contents = f.read().strip()
f.close()

How can I monitor client side inputs and send input requests from server every 5 seconds if no input is received?

I want to set up tcp server and client where server monitors client input and sends a request every 3 seconds if no input is received. Then client replies with its time. This goes on in an infinite loop. Also, they both have an option to exit the infinite loop. I don't know how to add the exit functionality as send(), recv() and input() block the code execution.
I have tried using select with 3 second timeout, it didn't work. I have tried threading but it stops after first user input until the next user input. I want it to go infinitely unless user wants to exit.
Infinite loop for communication:
client side:
while True:
data = ClientSocket.recv(1024).decode()
print("From Server: " + str(data))
# clear string
data = ''
data = 'Random Number: ' + str(random.randint(1, 101))
current_time = datetime.now()
required_format = (current_time.strftime("Date: %Y-%m-%d\tTime: %H:%M:%S.%f")[:-3])
data = data + "\t" + required_format + '\n'
ClientSocket.send(data.encode())
print("Sending: " + str(data))
data = ''
Server Side:
while True:
data = ''
data = 'Please enter a response.'
print("Sending: " + str(data))
ClientSocket.send(data.encode())
# clear string
data = ''
data = ClientSocket.recv(1024).decode()
print("From Client: " + str(data))
Select function that i tried:
readlist = [ClientSocket]
incoming = select.select(readlist, [], [], 3)
if incoming:
#perform a chat function here
else:
#use the code mentioned above for automated messages
This is the threading feature that I tried:
Python 3 Timed Input
How can I restrict time for recv(), send() and input() while sending and receiving message request and acknowledgements?
Please let me know if you would like to see the full code.
Something like this should work for you
server.py
inputs = [server]
outputs = []
messages = {}
try:
while inputs:
readable, writable, error = select.select(inputs, outputs, [])
for sock in readable:
if sock is server:
client, _ = sock.accept()
inputs.append(client)
messages[client] = Queue()
else:
data = sock.recv(1024).decode()
if data and data != 'exit\n':
print(data)
messages[sock].put(data)
if sock not in outputs:
outputs.append(sock)
else:
print('Client disconnected')
sock.close()
inputs.remove(sock)
for sock in outputs:
try:
msg = messages[sock].get_nowait()
sock.send(msg.upper().encode())
except Empty:
sleep(3)
sock.send(b'No data recieved')
outputs.remove(sock)
except KeyboardInterrupt:
server.close()
client.py
inputs = [sock, sys.stdin]
while inputs:
readable, _, _ = select.select(inputs, [], [])
for s in readable:
if s is sock:
data = sock.recv(1024).decode()
if data:
if data.lower() != 'exit':
print('{}'.format(data))
sys.stdout.write('You: ')
sys.stdout.flush()
else:
exiting('Server')
else:
exiting('Server')
else:
msg = sys.stdin.readline()
sock.send(msg.encode())
sys.stdout.write('You: ')

python sockets, trying to make a log in interaction betwen server and client

Hello so i have my server with a database (dictironay) and another passworddatabase
import socket
import sys
from _thread import *
host = ""
port = 8000
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket Created")
try:
serversocket.bind((host, port))
except socket.error as e:
print(str(e))
sys.exit()
database = {"name1" :{"hair" : "red", "size" : 1.50}}
password_database = {"name1": "1234",
"name2": "4321"}
def client_thread(conn): #threader client
welcome = "Welcome to the server. Type something and hit enter \n"
conn.send(welcome.encode("UTF-8"))
login(conn)
while True: # NOT IMPORTANT KEEP READING
data = conn.recv(24)
reply = data.decode("UTF-8")
if reply == "1":
menu1 = "Menu 1: Buy \n"
conn.send(menu1.encode("UTF-8"))
else:
wrong = "wrong option \n"
conn.send(wrong.encode("UTF-8"))
def login(conn): #MY LOGIC PROBLEM IS HERE
log = "Log in MENU: \n"
logi = log.encode("UTF-8")
conn.send(logi)
us = "Username: \n"
use = us.encode("UTF-8")
conn.send(use)
userr = conn.recv(24)
user = userr.decode("UTF-8")
pa = "Password: \n"
pasw = pa.encode("UTF-8")
conn.send(pasw)
passr = conn.recv(24)
passw = passr.decode("UTF-8")
tries = 0
while tries < 3:
if user in passwordDictionary and passwordDictionary[user] == passw:
print("Logged in")
menu()
else:
print("Wrong Username Or Password \n")
tries += 1
print("You failed the login too many times, blocking you out")
conn.close()
while 1: # NOT IMPORTANT
conn, addr = serversocket.accept()
print("Connected with " + addr[0] + ":" + str(addr[1]))
start_new_thread(client_thread, (conn, ))
serversocket.close()
Whats working:
The server is working fine, i'm having troubles doing the login on the client side.
client.py ==> client DOESNT go into the if data == Log in menu
is there a better way to do this?
#! /usr/bin/python3
import socket
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect(('localhost', 8000))
print("Connected")
datae = clientsocket.recv(24)
data = datae.decode("UTF-8")
clientsocket.send(datae)
while data != "!q":
if data == "Log in MENU: \n":
usere = input()
user = usere.encode("UTF-8")
clientsocket.send(user)
What would be the best way to create an log in interaction with the server?
the server has the usernames and passwords, i need to log in and then i need to edit the database depending on what user was chossen, but i'm having a hard time doing the algorithm
theres problems with the code you provided... however ill assume it actually works for you somehow and rather than copy paste you manually typed it
you are recieveing the first message here
datae = clientsocket.recv(24)
data = datae.decode("UTF-8") # GOT A MESSAGE
You then have the message datae = b'Welcome to the server. '
which does not match "Log in MENU: \n", and data != "!q" so it goes back into your loop and checks if data == "Log in MENU: \n" it doesnt so it repeats ... but you never get the next message instead try something like this second message
data = ""
while data != "!q":
if data == "Log in MENU: \n":
usere = input()
user = usere.encode("UTF-8")
clientsocket.send(user)
data = clientsocket.recv(24).decode("UTF-8") # GET THE NEXT MESSAGE!
but even then you are going to have problems because your server continues to write so you will get something like "Log in MENU: \nUsername" or something .... basically you need to work out a better message passing scheme than recv(24)
To avoid Errors try using a header with something like 64 Bytes wich always is the first message send. This Header is then used to send the actual length of the following message to the server. For example:
def send_response(conn, msg):
message = msg.encode(FORMAT)
send_length = len(str(len(message)).encode(FORMAT))
res_len = bytes(len(message)) + (b' ' * (HEADER - send_length))
print(f"[SENDING MESSAGE] {msg}")
conn.send(res_len)
conn.send(response)

Lua client, Python server, everything's fine in local, timeout on the net

So, I'm coding a lua mod for Binding of Isaac. I made a lua client (using luasocket), and a python server.
In local, everything works fine, but when I test it using my public ip (I did the port forwarding on my router), the lua client times out at its second reception.
I don't know what causes it, the log says "timeout at CID".
Edit (forgotten to add this) :
What is weird is that for the python server, it's as if he already sent it, because when I add a timeout on the server, it's only the reception of the message "[RCID]\n" that times out.
Here is the network part of the lua mod:
local socket = require("socket")
local connectIP = ""
local currentPort = 21666
local loopTimeout = 10
function Network.SendData(data)
if currentBehaviour == Behaviour.CLIENT then
client:send(data.."\n")
end
end
function Network.StartClient()
if currentBehaviour == Behaviour.IDLE then
client = assert(socket.tcp())
client:connect(connectIP,currentPort)
currentBehaviour = Behaviour.CLIENT
client:settimeout(loopTimeout)
local seed,errs = client:receive()
if errs~="timeout" and errs~=nil then
Network.CloseConnection();
Isaac.DebugString("seederror:"..errs);
elseif errs=="timeout" then
Network.CloseConnection();
Isaac.DebugString("timeout at seed");
elseif errs==nil then
Isaac.DebugString("Seed: : "..seed);
Isaac.ExecuteCommand("seed "..seed)
end
local CID,err = client:receive()
if err~="timeout" and err~=nil then
Network.CloseConnection();
Isaac.DebugString("ciderror:"..err);
elseif err=="timeout" then
Network.CloseConnection();
Isaac.DebugString("timeout at CID");
elseif err==nil then
Isaac.DebugString("CID : "..CID);
ClientID = tonumber(CID)
Network.SendData("[RCID]")
end
end
end
Here is the server :
import socket
import select
from parse import *
IsaacClients = {}
seed = b"98BN MJ4D\n"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('', 21666))
server.listen(10)
num_clients = 0
server_launched = True
connected_clients = []
while server_launched:
connections_asked, wlist, xlist = select.select([server],
[], [], 0.05)
for connection in connections_asked:
connection_client, info_client = connection.accept()
print(info_client)
connected_clients.append(connection_client)
print("Sending Seed")
connection_client.sendall(seed) # send the seed
print("Seed Sent")
num_clients = num_clients +1
check = ""
counter = 0
while check != "[RCID]\n" and counter<100: # try 100 times to send the ClientID
print("Sending ClientID")
try:
connection_client.settimeout(0.1)
connection_client.sendall((str(num_clients)+"\n").encode())
check = connection_client.recv(7).decode() # try to check if it has received it
connection_client.settimeout(None)
except:
pass
counter=counter+1
if counter == 100:
server_launched = False
print("ClientID Sent")
clients_to_read = []
try:
clients_to_read, wlist, xlist = select.select(connected_clients,
[], [], 0.05)
except select.error:
pass
else:
for client in clients_to_read:
msg_recved = client.recv(1024)
msg_recved = msg_recved.decode()
print("[] {}".format(msg_recved))
if msg_recved.find("[END]")!= -1 :
server_launched = False
msg_recved = msg_recved.split('\n') # split into lines
for line in msg_recved:
data = parse("[ID]{ID}[POS]{x};{y}[ROOM]{RoomIndex}[CHAR]{CharacterName}[REDM]{MaxHeart}[RED]{Hearts}[SOUL]{SoulHearts}", line)
if data != None :
IsaacClients[data['ID']] = data
luaTable = "{" # start the generation of the lua table that will be sent
for player in IsaacClients.values():
luaTable = luaTable + "[" + player['ID'] +"]={ID=" + player['ID'] + ",POS={x=" +player['x']+ ",y=" +player['y']+ "},ROOM=" +player['RoomIndex']+ ",CHAR='" +player['CharacterName']+ "',REDM=" +player['MaxHeart']+ ",RED=" +player['Hearts']+ ",SOUL=" +player['SoulHearts']+ "}"
luaTable = luaTable + "}\n"
print(luaTable)
print("Sending Table")
client.sendall(luaTable.encode())
print("Table Sent")
print("Server closing")
for client in connected_clients:
client.close()
So, finally, there was no issue, the thing was : my router didn't support hairpinning, making weird bugs when trying to use the public ip from the local network. It works fine whith PCs outside of the network.

Categories

Resources