Unable to transfer str to bytes in python 3 messaging service - python

I can't figure out how to transfer str to bytes in Python 3.
This is the client code:
import socket
import threading
tLock = threading.Lock()
shutdown = False
def receving(name, sock):
while not shutdown:
try:
tLock.acquire()
while True:
data, addr = socket.recvfrom(1024).decode()
print (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: ")
message = input(alias + "-> ")
while message != 'q':
if message != '':
s.sendto(alias.encode() + ": " + message.encode(), server.encode())
tLock.acquire()
message = input(alias + "-> ")
tLock.release()
time.sleep(0.2)
shudown = True
rT.join()
s.close()
This is the error I get:
Traceback (most recent call last):
File "C:/Python34/client fixing.py", line 35, in <module>
s.sendto(alias.encode() + ": " + message.encode(), server.encode())
TypeError: can't concat bytes to str
>>>

This is because ":" is an str (string) object. You could just do b':':
s.sendto(alias.encode() + b": " + message.encode(), server.encode())
but you might find it simpler if you used str.format().encode()
s.sendto("{}: {}".format(alias, message).encode(), server.encode())

In the line
s.sendto(alias.encode() + ": " + message.encode(), server.encode())
": ", which is a string, is being concatenated with two bytestrings (we know they're bytestrings because .encode() is called on them. This is an error in Python3, but it can be fixed by calling .encode() on the string.
The second parameter to Socket.sendto should be an address. The exact type of the address depends on the socket's family. In this case you have correctly defined address as a tuple (server = ('127.0.0.1',5000)), but you are erroneously calling .encode() on it.
Try changing the line to:
s.sendto(alias.encode() + ": ".encode() + message.encode(), server)
and the error will be fixed.

Related

Python 3.8 TypeError: can't concat str to bytes - TypeError: a bytes-like object is required, not 'str'

Very new to coding. This was the initial code I was trying to get to run but have found it is incompatible with python 3 because of how it handles strings and bytes.
def opensocket():
s = socket.socket()
s.connect((HOST,PORT))
s.send("PASS " + PASS + "\r\n")
s.send("NICK " + IDENT + "\r\n")
s.send("JOIN #" + CHANNEL + "\r\n")
return s
I think I need to encode these strings into bytes but all the conversion methods I've tried have given errors. here are some i've tried.
def opensocket():
s = socket.socket()
s.connect((HOST,PORT))
s.send(b"PASS " + PASS + "\r\n")
s.send(b"NICK " + IDENT + "\r\n")
s.send(b"JOIN #" + CHANNEL + "\r\n")
and
def opensocket():
s = socket.socket()
s.connect((HOST,PORT))
s.send("PASS " + PASS + "\r\n".encode())
s.send("NICK " + IDENT + "\r\n".encode())
s.send("JOIN #" + CHANNEL + "\r\n".encode())
return s
both of these give errors saying the str can't be concatenated into bytes
any help?
edit: went through the suggested post but I'm gaining nothing from that. it looks so different and I'm so new to this that I can't even tell where the string was he was trying to convert
In the case that PASS, IDENT and CHANNEL are bytes:
def opensocket():
s = socket.socket()
s.connect((HOST,PORT))
s.send(b"PASS " + PASS + b"\r\n")
s.send(b"NICK " + IDENT + b"\r\n")
s.send(b"JOIN #" + CHANNEL + b"\r\n")
In the case that PASS, IDENT and CHANNEL are str:
def opensocket():
s = socket.socket()
s.connect((HOST,PORT))
s.send(b"PASS " + PASS.encode('ascii') + b"\r\n")
s.send(b"NICK " + IDENT.encode('ascii') + b"\r\n")
s.send(b"JOIN #" + CHANNEL.encode('ascii') + b"\r\n")
It's important to know what protocol you're using, to know what encoding actually to use. 'ascii' is a safe bet, but it means you're limited in to ASCII-only characters, so if the protocol actually specifies UTF-8 strings, you should do .encode('utf-8') instead.

python UDP socket client need to send twice so that the server can receive the package

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)

I need help understanding threads utilisation

I'm setting up a little server with commands and other kind of stuff, but ,I don't get the thread functionement, when I connect my server it seems like everything is okay, I can connect a first client "without" problems, but when I want to connect another client it never get conected , the code runs but I can send anything I want it never shows up on the other client or the server.
I've already read the Threading documentation but even with the exemples, I don't get it, can someone give me some clues about how to proceed to handle more than just one client?
the server code :
#!/usr/bin/python3+x
import socket
import sys
from time import sleep
import threading
import random
HOST = "localhost"
PORT = 33700
MSG_SIZE = 32768
serveur_on = True
CLIENT_NICK_CHAN = {} #clients" nicks dict like {nickname : channel} -> needed to easily know who is where
CLIENT_NICK_SOCKET = {} #clients" dict like {nickname : socket} -> needed to send private message to the nickname's socket easily
CLIENT_NICK_THREAD = {} #clients" dict with like {nick : thread}
Rand_disconnection_msg = [" has drown in the abyss.", " is disconnected.", " is now in a better place.", " is now a part of our past", " passed away, in really tragic circumstances..."]
CHANNELS = ["main lobby", "test"]
CMD_LIST = [b"HELP",b"NICK",b"JOIN",b"CHANNELS",b"LEAVE"]
COMMANDS = ["/NICK <nickname>: Use only when you\'re connecting, allow you to choose a unique nickname",
"/JOIN <channel_name>: Allow you to join or create a channel, you can\'t use this command if your are already in another channel than the" + CHANNELS[0],
"/CHANNELS : Allow you to see every channels on the server with every connected people",
"/LEAVE : You leave the channel your within and get bringed back to the" + CHANNELS[0],
"/HELP : Gives you the whole command list",
"/BYE : Disconnect ou from the server, you have to in the " + CHANNELS[0] + " to use this command"
]
class Colors:
Blue, Cyan, Green, Red, Magenta, Yellow, White =b"\033[94m", b"\033[96m", b"\033[92m", b"\033[91m", b"\033[95m", b"\033[93m", b"\033[0m"
Normal, Bold, Italics, Thin = b"\033[0m", b"\033[1m", b"\x1B[3m", b"\033[2m"
class thread_client(threading.Thread):
def __init__(self,conn):
self.nom = ""
if(self.nom == ""):
nickname_input(connexion, self)
print("nom : " + self.nom.decode("utf8"))
self.channel = CHANNELS[0]
self.admin = False
self.adress = ""
threading.Thread.__init__(self)
self.connexion = conn
print("init done")
def run(self):
while True:
msgClient = self.connexion.recv(MSG_SIZE)
if not msgClient or msgClient == b"BYE":
break
print(type(self.nom))
print(type(msgClient))
str_name = self.nom.decode("utf8")
msg = str_name + " > " + msgClient.decode("utf8")
print("string type name is : " + str_name + "\n")
str_msg = msgClient.decode("utf8")
print("{} > {}".format(str_name, str_msg))
for clients in CLIENT_NICK_SOCKET:
if clients != self.nom:
CLIENT_NICK_SOCKET[clients].send(bytes(str_msg,"utf8"))
self.connexion.send(b"You are now disconnected.\n")
self.connexion.close()
del CLIENT_NICK_SOCKET[self.nom.decode("utf8")]
del CLIENT_NICK_CHAN[self.nom.decode("utf8")]
rand_leave = random.randint(0, len(Rand_disconnection_msg)-1)
leaving_msg = Rand_disconnection_msg[rand_leave]
print(str_name + leaving_msg + "\n")
def nickname_input(client_socket, thread):
print("now in input nickname")
msg_nom = client_socket.recv(MSG_SIZE)
print("msg_nom = " + msg_nom.decode("utf8"))
msg_nom_arr = msg_nom.split()
if not msg_nom_arr[0]:
client_socket.send(b"Please send a non void message")
nickname_input(client_socket, thread)
print("msg_nom_arr[0] = " + str(msg_nom_arr[0]))
if(msg_nom_arr[0] == b"NICK"):
if(len(msg_nom_arr)== 1):
client_socket.send(b"Please do not just enter '/NICK' -> you have to type '/NICK <your_nickname>', please proceed again :\n")
nickname_input(client_socket, thread)
else:
thread.nom = msg_nom_arr[1]
else:
client_socket.send(b"It seems like you forgot to use '/NICK' before entering your nickname, please proceed again:\n")
nickname_input(client_socket, thread)
return
def print_channels(client_socket, thread):
client_socket.send(b"Here\'s the current channel list :\n\n")
for chan in CHANNELS:
sleep(0.70)
client_socket.send( bytes(chan,"utf8") + b":\n current members :\n")
for chan_user in CLIENT_NICK_CHAN:
if(CLIENT_NICK_CHAN[chan_user] == chan):
sleep(0.35)
if(chan_user == thread.nom):
if(thread.admin):
client_socket.send(b" " +Colors.Bold + Colors.Yellow + b"#"+ thread.nom + b"#" + Colors.Normal + b"\n")
else:
client_socket.send(b" " +Colors.Bold + Colors.Yellow + thread.nom + Colors.Normal + b"\n")
else:
client_socket.send(b" " +bytes(chan_user,"utf8") + b"#\n")
client_socket.send(b"\n")
client_socket.send(b"\n")
return
def join_channel(client_socket, thread, data, data_array):
if(not data_arr[1]):
connexion.send(b"Please select a channel you want to join using '/JOIN <channel_name>'\nNote that if the channel you asked for doesn\'t exists a new channel <channel_name> will be created and you will be the administrator of this channel")
return
else:
asked_channel = data_arr[1]
if( not (asked_channel in CHANNELS)):
thread.channel = asked_channel
thread.admin = True
connexion.send(b"Welcome in " + asked_channel + b" channel, since you\'re the on who created this channel you are granted as administrator for this channel")
connexion.send(b"Note that being administrator allow you tu use some new commands as '/GRANT', '/REVOKE' or '/REN', for more information please use '/HELP'")
else:
thread.channel = asked_channel
connexion.send(b"Welcome in " + asked_channel + b" channel !")
return
SERVER = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
SERVER.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
try:
SERVER.bind((HOST,PORT))
except socket.error:
print("Server connexion failed")
sys.exit()
print("Server is now connected\nWaiting for connexions...\n")
SERVER.listen(5)
connexion, adresse = SERVER.accept()
thread = thread_client(connexion)
thread.start()
print("thread type = " +str(type(thread)) +"\n")
print("thread = ")
print(thread)
connexion.send(bytes("Welcome ","utf8") + Colors.Yellow + Colors.Bold + thread.nom + Colors.Normal)
nick = thread.nom #type -> bytes
str_nick = nick.decode("utf8")
CLIENT_NICK_CHAN[str_nick] = thread.channel
CLIENT_NICK_SOCKET[str_nick] = connexion
CLIENT_NICK_THREAD[str_nick] = thread
print("client list : ")
print(CLIENT_NICK_CHAN)
print("\n")
print("CLIENT_NICK_SOCKET = ")
print(CLIENT_NICK_SOCKET)
print("\n")
while serveur_on:
conn_msg = str_nick + " joined the chat\n"
print(conn_msg)
connexion.send(b"hello world 3\n\n")
connexion.send(b"*" * 80 + b"\n")
connexion.send(Colors.Red + Colors.Bold + b"\nWELCOME IN THE MAIN LOBBY \n" + Colors.Normal+b"\nTo enter a channel use '/JOIN <channel_name>'\nthe <channel_name> have to be composed by one world or use underscores to join words\nIf the channel does not exists a new one will be created\n\nNote that you have to be in another channel than the main lobby to chat\n")
print_channels(connexion, thread)
connexion.send(b"*" * 80 + b"\n\n")
while True:
print("thread list = ")
print(CLIENT_NICK_THREAD)
data = connexion.recv(MSG_SIZE) #receiving data from client
data_arr= data.split() #convert data into an array to check if the first word in the message is "MSG" or not
print(str_nick +" is now in -> " + thread.channel + "\n")
if(data_arr[0] in CMD_LIST):
if(data.startswith(b"HELP")): #HELP CMD
for command in COMMANDS:
connexion.send(bytes(command,"utf") + b"\n")
if(data.startswith(b"CHANNELS")): #Channels + current members CMD
connexion.send(b"\n")
print_channel(connexion, thread)
connexion.send(b"\n")
if(data.startswith(b"JOIN")):
join_channel(connexion, thread, data, data_arr)
connexion.send(b"\n")
else:
if ((thread.channel != CHANNELS[0]) and (data.startswith("MSG"))):
for chan_user in thread.channel:
chan_user.send(nick + b" > " + bytes(data,"utf8"))
print("data = " + data)
elif (thread.channel == CHANNELS[0]):
connexion.send(b"You have to be in another channel than the " + bytes(CHANNELS[0], "utf8") + b" to start chating !\nPlease use '/JOIN <channel_name>' or '/HELP' to learn how to join another channel.\n\n")
and the client code:
#!/usr/bin/python3+x
host = ''
port = 33700
MSG_SIZE = 32768
emission_stop = False
import socket
import sys
import threading
import time
def Tsend():
while True:
msg_envoi = input("> ")
if msg_envoi.startswith("/"):
msg_envoi = msg_envoi.replace("/","",1)
else:
msg_envoi = msg_envoi
CLIENT.send(bytes(msg_envoi,"utf8"))
if emission_stop:
CLIENT.close()
def Trecv():
while True:
msg_recu = CLIENT.recv(MSG_SIZE).decode("utf8")
print("\n" + msg_recu)
if not msg_recu:
break
emission_stop = True
print("connexion lost\n")
CLIENT.close()
CLIENT = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
try:
CLIENT.connect((host,port))
except socket.error:
print("connexion failed\n")
sys.exit()
print("Now connected to the server on port: {}\n".format(port))
print("Please now enter your nickname using '/NICK'\n")
thread_emission = threading.Thread(target = Tsend)
thread_reception = threading.Thread(target = Trecv)
thread_emission.start()
thread_reception.start()
What I want is just to have multiple clients that are allowed to talk to each other but I can't even get two clients.
The biggest problem I can see is that you are only calling SERVER.accept() once. This means you will only ever accept 1 client connection. When using blocking sockets as you are, a typical approach is to keep doing SERVER.accept() inside a loop so that you can keep accepting all client sockets. After you accept() a new socket, you create new thread(s) dedicated to sending/receiving for that socket, so that you don't block the accepting thread. And then you continue accepting more connections. Something like this:
#SERVER:
while serveur_on:
connexion, adresse = SERVER.accept()
# Possibly do some limited IO with client socket here, but be careful not
# to block this thread too long because that will prevent more clients from
# connecting.
thread = thread_client(connexion)
thread.start()
# No more client IO on this thread, it's the client thread's job now.
You seem to have code that communicates with the client (receiving messages and sending responses) in 2 different places: on the main thread after you SERVER.accept(), and up in thread_client.run(). It doesn't make sense that way, it should all be in thread_client.run().

Python TypeError with sockets

import socket, sys, string
if len(sys.argv) !=4:
print ("UsageL ./ninjabot.py <server> <port> <channel>")
sys.exit(1)
irc = sys.argv[1]
port = int(sys.argv[2])
chan = sys.argv[3]
sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sck.connect((irc, port))
sck.send(b'NICK ninjabot\r\n')
sck.send(b'USER ninjabot ninjabot ninjabot :ninjabot Script\r\n')
sck.send('JOIN ' + " " + chan + '\r\n')
data = ''
while True:
data = sck.recv(1024)
if data.find('PING') != -1:
sck.send('PONG ' + data.split() [1] + '\r\n')
print (data)
print (data)
I get this error in sck.send('JOIN ' + " " + chan + '\r\n') but when i try this:
sck.send(b'JOIN ' + " " + chan + '\r\n')
I get TypeError: can't concat str to bytes
I know there's similar posts with this same issue, but none of those seem to help me.
This is due to the fact that b'JOIN' is of type bytes while " " as well as chan and "\r\n" are of type str.
2 corrections:
chan = sys.argv[3].encode()
sck.send(b'JOIN ' + b" " + chan + b'\r\n')
alternatively you could just:
sck.send(b'JOIN %s\r\n' % chan.encode())
this would be the best style. Similar corrections will be need to be made later in your snippet as well. socket.send is looking for a bytes string, so ensure that all strings which you pass it are either b"" or encoded otherwise using encode()

Creating a simple IRC bot in python. Having trouble

So a few hours ago I decided to try my hands on sockets with python and build a simple irc bot. So far I'm having some trouble getting it connected to the server. I get the following erros:
b":irc.ku.cx 439 * :Please wait while we process your connection.\r\n:irc.ku.cx NOTICE AUTH :*** Couldn't look up your hostname (cached)\r\n"
b':irc.ku.cx NOTICE AUTH :*** Checking Ident\r\n'
b':irc.ku.cx NOTICE AUTH :*** No Ident response\r\n'
After that it stalls out. But about a minute of it running I suddenly get an endless amount of b"", each in a new line (probably something to do with the while loop in the code). This is my code:
import socket
server = 'irc.rizon.net'
channel = '#linux'
nick = 'MyBot'
port = 6667
ircsock = socket.socket()
ircsock.connect((server, port))
ircsock.send(bytes('"NICK " + nick', 'UTF-8'))
ircsock.send(bytes('"USER " + nick + " " + nick + " " + nick + " :" + nick', 'UTF-8'))
while True:
data = ircsock.recv(2048)
print (data)
if data.find(b"PING") != -1:
ircsock.send(b"PONG :" + data.split(':')[1])
Thanks for any help you guys can provide.
As icktoofay said, there are extra quotes in your code. Also, in IRC you need to add a line break (\r\n) to the end of every command.
Replace these lines:
ircsock.send(bytes('"NICK " + nick', 'UTF-8'))
ircsock.send(bytes('"USER " + nick + " " + nick + " " + nick + " :" + nick', 'UTF-8'))
with
ircsock.send(bytes("NICK " + nick + "\r\n", 'UTF-8'))
ircsock.send(bytes("USER " + nick + " " + nick + " " + nick + " :" + nick + "\r\n", 'UTF-8'))
and it should work.
By the way, I recommend using socket.makefile() instead, which handles buffering and encoding for you. Here's your code modified to use the file interface:
import socket
server = 'irc.rizon.net'
channel = '#linux'
nick = 'MyBot'
port = 6667
ircsock = socket.socket()
ircsock.connect((server, port))
handle = ircsock.makefile(mode='rw', buffering=1, encoding='utf-8', newline='\r\n')
print('NICK', nick, file=handle)
print('USER', nick, nick, nick, ':'+nick, file=handle)
for line in handle:
line = line.strip()
print(line)
if "PING" in line:
print("PONG :" + line.split(':')[1], file=handle)
Here, I use the print function which inserts spaces and newlines automatically.

Categories

Resources