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.
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'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().
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()
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.