Python Client/Server loop error if I print something - python

Repo is here: https://gitlab.com/andrzej_stopka/battleship/-/tree/client-server-communication
I make the battleship game in Python. It is working with sockets I'll show screen when I have problem.
Server.py/locate_ships()
def locate_ships(self, conn):
## It get inputs from a client to locate him ships
server_board = Board()
user_board = Board()
server_board.locate_server_ships()
for ship in user_board.ships:
while True:
arrangement = board_arrangement(user_board.board) # convert user board to message
conn.send(bytes(json.dumps(arrangement), encoding="utf-8"))
request = cord_request(ship.name, ship.occupied_spaces()) # convert ship info to message
conn.send(bytes(json.dumps(request), encoding="utf-8"))
cord = json.loads(conn.recv(1024)) # get user info
cord = cord["body"] # cords in message body
result = user_board.place_user_ship(ship, cord)
# insert cords to function to place ship on the board if input is valid
if ship == user_board.ships[-1]:
result = "Done"
server_acceptance = cord_answer(result) # convert to message if input is valid
conn.send(bytes(json.dumps(server_acceptance), encoding="utf-8"))
if result == "Placed": # if input is valid, go to the next ship
break
Client.py/main()
def main():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
input("You are now connected to the Battleship server, press any key to continue")
s.send(bytes(game_invitation, encoding="UTF-8"))
acceptance = json.loads(s.recv(1024))
if acceptance["status"] == 0: # if status is equal 0 it means that server is ready to game
while True:
board_arrangement = json.loads(s.recv(1024))
print(board_arrangement)
show_board(board_arrangement["body"]) # print actual state of the board
cord_request = json.loads(s.recv(1024)) # it is request from server to give ship cords you want
cords = enter_cord(cord_request["message"]) # input
cords = json.dumps(ships_cords(cords[0], cords[1], cords[2])) # convert cords to a message
s.send(bytes(cords, encoding="utf-8"))
acceptance = json.loads(s.recv(1024)) # check if input was valid
if acceptance["message"] == "Done":
print("Locating is done")
break
else:
print(acceptance["message"])
continue
Problem is with last print - print(acceptance["message"]. If I put it in my code after first loop's run I get error - raise JSONDecodeError("Extra data", s, end)
json.decoder.JSONDecodeError: Extra data: line 1 column 560 (char 559) in board_arrangement = json.loads(s.recv(1024)) in second loop's run, it receives None object. Moreover if I put print() anywhere in server/locate_ships function the app is working well. It seems that after this print there is problem with communication between server and client but I don't know why and where. Is it possible that print() spoils communication?
Thanks in advance :)
I tried almost everything. I know that I could put empty print() on locate_ships in server.py but I don't want to do it and I want to get to know why the error appears.

Related

How can I properly run 2 threads that await things at the same time?

Basically, I have 2 threads, receive and send. I want to be able to type a message, and whenever I get a new message it just gets 'printed above the line I am typing in'. first what I thought would work, and you can just paste this it will run:
import multiprocessing
import time
from reprint import output
import time
import random
import sys
def receiveThread(queue):
i = 0
while True:
queue.put(i)
i+=1
time.sleep(0.5)
def sendThread(queue):
while True:
a = sys.stdin.read(1)
if (a != ""):
queue.put(a)
if __name__ == "__main__":
send_queue = multiprocessing.Queue()
receive_queue = multiprocessing.Queue()
send_thread = multiprocessing.Process(target=sendThread, args=[send_queue],)
receive_thread = multiprocessing.Process(target=receiveThread, args=[receive_queue],)
receive_thread.start()
send_thread.start()
with output(initial_len=2, interval=0) as output_lines:
while True:
output_lines[0] = "Received: {}".format(str(receive_queue.get()))
output_lines[1] = "Last Sent: {}".format(str(send_queue.get()))
But what happens here is that i cannot send data. The input doesn't give me an EOF unlike when I put a = input(), but it overwrites whatever I put in that line, so how can I wait for the input in one thread while the other one works?
EXPECTED BEHAVOIR:
first line goes Received: 0, 1, 2, 3, 4...
second line goes [my input until I press enter, then my input]
ACTUAL BEHAVIOR if i don't check if input != ""
first line as expected only that the input overwrites the first couple of letters until it resets to Received
second line is always empty, maybe bc stdin only is filled for that one time i press enter and then always returns empty?
ACTUAL BEHAVIOR if i check if input != ""
first line stays: received = 0
second line is just like whatever i enter, if i press enter it goes into a new line where i then enter stuff
Don't use the same socket for communicating with... itself. That may be possible to do, I'm not sure, but it certainly isn't normal. Instead make a socket pair, one for the sending thread, and one for the receiving thread, e.g. this works for me:
import socket;
import multiprocessing;
def receiveThread(sock):
while True:
msg = sock.recv(1024)
print(msg.decode("utf-8"))
def sendThread(sock):
while True:
# msg=input("client: ")
# input() is broken on my system :(
msg="foo"
sock.send(bytes(msg,"utf8"))
pair = socket.socketpair()
recieve_thread_socket = pair[0]
send_thread_socket = pair[1]
send_thread = multiprocessing.Process(target=sendThread, args=[recieve_thread_socket])
receive_thread = multiprocessing.Process(target=receiveThread,args=[send_thread_socket])
send_thread.start()
receive_thread.start()

Downloading a webpage using urllib3

I'm trying to write a program for an assignment that uses urllib3 to download a webpage and store it in a dictionary. (I'm using spyder 3.6)
The program is giving me an 'AttributeError' and I have no idea what I'm doing wrong. here is my code with step by step notes I wrote for the assignment.
#Downloading a webpage
import urllib3
import sys
#these import statements allow us to use 'modules' aka 'libraries' ....
#code written by others that we can use
urlToRead = 'http://www.google.com'
#This value won't actually get used, because of the way the while loop
#below is set up. But while loops often need a dummy value like this to
#work right the first time
crawledWebLinks = {}
#Initialize an empty dictionary, in which (key, value) pairs will correspond to (short, url) eg
#("Goolge" , "http://www.google.com")
#Ok, there is a while loop coming up
#Here ends the set up
while urlToRead != ' ':
#This is a condition that dictates that the while loop will keep checking
#as long as this condition is true the loop will continue, if false it will stop
try:
urlToRead = input("Please enter the next URL to crawl")
#the "try" prevents the program from crashing if there is an error
#if there is an error the program will be sent to the except block
if urlToRead == '':
print ("OK, exiting loop")
break
#if the user leaves the input blank it will break out of the loop
shortName = input("Please enter a short name for the URL " + urlToRead)
webFile = urllib3.urlopen(urlToRead).read()
#This line above uses a ready a readymade function in the urllib3 module to
#do something super - cool:
#IT takes a url, goes to the website for the url, downloads the
#contents (which are in the form of HTML) and returns them to be
#stored in a string variable (here called webFile)
crawledWebLinks[shortName] = webFile
#this line above place a key value pair (shortname, HTML for that url)
#in the dictionary
except:
#this bit of code - the indented lines following 'except:' will be
#excecuted if the code in the try block (the indented following lines
#the 'try:' above) throw and error
#this is an example of something known as exeption-handling
print ("*************\nUnexpected Error*****", sys.exc_info()[0])
#The snip 'sys.exc_info()[0]' return information about the last
#error that occurred -
#this code is made available through the sys library that we imported above
#Quite Magical :)
stopOrProceed = input("Hmm..stop or proceed? Enter 1 to stop, enter anything else to continue")
if stopOrProceed ==1 :
print ('OK...Stopping\n')
break
#this break will break out of the nearest loop - in this case,
#the while loop
else:
print ("Cool! Let's continue\n")
continue
# this continue will skip out of the current iteration of this
#loop and move to the next i.e. the loop will reset to the start
print (crawledWebLinks.keys())
Your issue is that you are trying to call urllib3.urlopen(), and urllib3 does not have a member urlopen Here is a working snippet. All that I did was replace urllib3 with urllib.request:
import urllib.request
import sys
urlToRead = 'http://www.google.com'
crawledWebLinks = {}
while urlToRead != ' ':
try:
urlToRead = input("Please enter the next URL to crawl: ")
if urlToRead == '':
print ("OK, exiting loop")
break
#if the user leaves the input blank it will break out of the loop
shortName = input("Please enter a short name for the URL " + urlToRead + ": ")
webFile = urllib.request.urlopen(urlToRead).read()
crawledWebLinks[shortName] = webFile
except:
print ("*************\nUnexpected Error*****", sys.exc_info()[0])
stopOrProceed = input("Hmm..stop or proceed? Enter 1 to stop, enter anything else to continue")
if stopOrProceed ==1 :
print ('OK...Stopping\n')
break
else:
print ("Cool! Let's continue\n")
continue
print (crawledWebLinks)
Another note, simply printing out the type of error in your except block is not very useful. I was able to debug your code in 30 seconds once I removed that and viewed the actual traceback.

Socket issue when using threads

I've been working on a python game in my spare time, and I've run into a problem. I'm working with sockets using the basic threads module, and it works fine when I connect to the server file with one client. But more than that, and any that connect after the first freezes up the server and the first client.
Here is the code for the server
import socket
import random
import thread
from saveState import Save
from grid import Grid
import time
players = 0
save = Save()
grid = Grid()
def ready(c):
ready = raw_input("Are you ready to play?\n")
if(ready == "yes" or ready == "y"):
grid.makeGrid()
c.send("ready")
def clientThread(conn,players):
while True:
print "taking requests"
request = conn.recv(1024)
segments = request.split(",,")
if(segments[0] == "0" and players<200):
print "registering player", addr
serial = random.choice(list(range(999999)))
conn.send("{}".format(serial))
save.players[serial] = segments[2:]
print save.players[serial][9]
players+=1
elif(segments[0] == "3"):
if(segments[2] == "land"):
conn.send("{},,{},,{},,{}".format(grid.getLandType(int(save.players[serial][9]),int(save.players[serial][10])), grid.getDesc(int(save.players[serial][9]),int(save.players[serial][10])),int(save.players[serial][9]),int(save.players[serial][10])))
elif(segments[0]=="2"):
if(segments[2]=="playerX" and int(segments[3])==-1):
save.players[serial][9] = int(save.players[int(serial)][9])-1
elif(segments[2]=="playerX"):
save.players[serial][9] = int(save.players[int(serial)][9])+1
if(segments[2]=="playerY" and int(segments[3])==-1):
save.players[serial][10] = int(save.players[int(serial)][10])-1
elif(segments[2]=="playerY"):
save.players[serial][10] = int(save.players[int(serial)][10])+1
elif(segments[0]=="4"):
alreadySent = []
for m in grid.monsters:
if(m.X==save.players[int[segment[1]]][9] and m.Y==save.players[int[segment[1]]][10] and alreadySent[m]==False):
conn.send("{},,{}".format(m.name, True))
elif(time.clock == 60*60*(12+8)):
conn.send("{},,{}".format("You see the sun set on the horizon. Monsters will be more aggressive now.", False))
else:
print "sorry, there is an inconsistency in the request or the queue is full."
try:
#start up socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
name = socket.gethostbyname(socket.gethostname())
print name
port = input("select port\n")
s.bind((name, port))
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
#listen for any attempts to connect to the api
#if anyone connects, give them a serial number and add their data to a storage file
while True:
s.listen(5)
c,addr = s.accept()
thread.start_new_thread(ready,(c,))
thread.start_new_thread(clientThread,(c, players))
conn.close
sock.close
except socket.error:
print " either the server port is closed or in use. try again"
and the client
import random
from grid import Grid
from player import Player
from descriptions import Descriptions
import socket
import time
import thread
description = Descriptions()
def descisionHandler(s,serial):
while True:
s.send("{},,{},,{}".format(3,serial,"land"))
response = s.recv(1024).split(",,")
print "you are on a {} tile \n {} \n {} \n {}".format(response[0], response[1],response[2], response[3])
action=raw_input("What Will You Do?\n")
try:
if(action == "west" and player.locX>0):
s.send("{},,{},,{},,{}".format(2,serial,"playerX",-1))
time.sleep(0.5)
elif(action == "east" and player.locX<199):
s.send("{},,{},,{},,{}".format(2,serial,"playerX",1))
time.sleep(0.5)
elif(action == "north" and player.locY>0):
s.send("{},,{},,{},,{}".format(2,serial,"playerY",-1))
time.sleep(0.5)
elif(action == "south" and player.locY<199):
s.send("{},,{},,{},,{}".format(2,serial,"playerY",1))
time.sleep(0.5)
# elif(action == "attack" and monster_data[1]):
# print "The {} wakes up! A battle begins!".format(monster_data[0])
elif(action == "profile"):
print " You are {} \n {} \n your role is {} \n you have an attack of {} \n a defense of {} \n a speed of {} \n and {} hitpoints \n attacks: {} \n you are located at {} {}".format(player.name,
player.backstory,player.role,player.attack,player.defense,player.speed, player.hitpoints, player.attacks, player.locX, player.locY)
elif(action == "exit"):
break
except IndexError:
pass
def eventHandler(s,serial):
while True:
s.send("{},,{}".format(4,serial))
response = s.recv(1024).split(",,")
print response[0]
return bool(response[1])
while True:
try:
print "\nWelcome to Overseer! We need a few things before we begin\n"
name = raw_input("What is your name?\n")
backstory = raw_input("What is in your past: choose one \n chosen \n magician \n poet\n")
role = raw_input("what is your class: choose one \n Warrior \n Mage \n Rougue \n Bard\n")
player = Player(name,description.player_backstory[backstory], role, 5,5,5,10, {"scrap": 10}, random.choice(list(range(200))), random.choice(list(range(200))))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = raw_input("what host are you connecting to?")
port = input("what port?\n")
s.connect((host,port))
print "connection successful."
time.sleep(5)
s.send("{},,{},,{},,{},,{},,{},,{},,{},,{},,{},,{},,{},,{}".format(0,0,name,backstory,role,5,5,5,5,10,player.attacks,player.locX,player.locY))
serial = s.recv(1024)
print "You're serial number is {}".format(serial)
while(s.recv(1024) != "ready"):
pass
break
except socket.error:
print "server is not running or is busy. please try again."
eventThread = thread.start_new_thread(eventHandler,(s,serial))
descisionThread = thread.start_new_thread(descisionHandler,(s,serial))
while 1:
pass
I did a bit of research and my best guess is that I need to use locks from the threading module, but I'm not sure. any suggestions?
Thanks in advance!
So the issue was the console input, as theSmallNothing said. There wasn't really a way around this limitation without serious hacking, so I proposed to improvise. My solution was to create a web app with python instead of using a console. There were a few advantages to this.
the server can handle multiple inputs at a time easily
things can happen while input is being entered(the solution to my problem)
no files need be downloaded for the user as everything can be accessed simply by entering the web address.
While not a perfect solution, sometimes finding an alternative is the next best thing.
Thanks all for your awesome help!

Python socket server/client not looping

I'm working on a number guessing game handled over two clients connected via socket, but for some reason after the initial loop it stops working and doesn't send/receive anything. The code all executes fine the first time around, but no matter what I change, the second time around I either get an error at the line guessNumber = int(s.recv(4096).decode() in the server file - where it reports an error trying to change '' into an int. This implies it's not receiving a value (in these instances, the Client program doesn't receive the "What is your guess? " string either).
The code below however just doesn't do anything after that initial loop, If you guess the number on that first loop then it works fine, your score is written to a file and they both end as they should.
But if you don't then it doesn't do anything either, so any help would be appreciated. It's running in Python 3.4.2 using the IDLE IDE.
Server:
import socket
import random
l = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
score = 0
guessNumber = 0
def within(value, goal, n):
numDifference = abs(value - goal)
if (numDifference <= n):
return True
else:
return False
scoreFile = open('scores', 'a')
randomNumber = random.randrange(0, 11)
l.bind(("127.0.0.1", 4001))
l.listen(5)
print("Waiting...")
while True:
(s,ca)=l.accept()
print("Connection from", ca)
while (not(within(guessNumber, randomNumber, 0))):
s.sendall("What is your guess? ".encode())
guessNumber = int(s.recv(4096).decode())
score += 1
print ("%d" % guessNumber)
if (within(guessNumber, randomNumber, 0)):
s.sendall(("You guessed correctly! \n Your score is %d" % score).encode())
scoreFile.write("Player %s has a score of %d \n" % (ca, score))
scoreFile.close()
s.sendall("1".encode())
elif (within(guessNumber, randomNumber, 3)):
s.sendall("You are getting close!".encode())
s.sendall("0".encode())
else:
s.sendall("You are way off".encode())
s.sendall("0".encode())
s.close()
Client:
import socket
gameOver = False
guessNumber = 0
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", 4001))
while (gameOver != "1"):
#Send guess
guessNumber = input(s.recv(4096).decode())
s.sendall(guessNumber.encode())
#Recieve result
print(s.recv(4096).decode())
#Check whether game is over or not
gameOver = s.recv(4096).decode()
print ("Game Over")
s.close()
It turns out the client was closing it's socket after the first iteration because it ended with a receive. I've added some send confirmations after each receive to tell the Server it was performed successfully, and now all works as intended!

python multithreaded sniffer- exit from thread

I have created a packet sniffer in python using scapy but kind of stuck in the multithreaded stuff..
def sniffer(ip):
filter_str = "icmp and host " + ip
packets=sniff(filter=filter_str,count=20)
status= False
for p in packets:
packet_load=str(p['Raw'].load)
if packet_load.find("##")!= -1:
status=True
log_thread = Thread(target=logger,args=(packets,))
log_thread.start()
log_thread.join()
break
if status==True:
print "Suspicious Packets sniffed!!"
user_ip = raw_input("Do you want to continue sniffing???(y/n)")
while 1:
if user_ip=="y" or user_ip=="Y":
new_thread = Thread(target=sniffer, args=(ip,))
new_thread.start()
new_thread.join()
else:
#need somthing to quit the program
return
Here, my sniffer sniffs 20 packets at a time and waits for user input for further sniffing.
However if the user enters 'n' as input, then the program hangs. Ideally I would want the program to quit if the user enters 'n'. Can I know what I'm doing wrong here??
while 1 is rarely a good choice when writing a finite loop. Try using flags instead:
leaving = False
while not leaving:
user_ip = raw_input("Do you want to continue sniffing???(y/n)")
if user_ip.lower() == 'y':
new_thread = Thread(target=sniffer, args=(ip,))
new_thread.start()
new_thread.join()
elif user_ip.lower() == 'n':
print "Leaving sniffer"
leaving = True
return

Categories