I am writing a multi-chat which consists of the Client handler, the server and chat record. The Client should allow multiple chats. At the moment it doesn't allow for even one chat, I get an error message after the name has been entered.
This is the Client handler file
from socket import*
from codecs import decode
from chatrecord import ChatRecord
from threading import Thread
from time import ctime
class ClientHandler (Thread):
def __init__(self, client, record):
Thread.__init__(self)
self._client = client
self._record = record
def run(self):
self._client.send(str('Welcome to the chatroom!'))
self._name = decode(self._client.recv(BUFSIZE),CODE)
self._client.send(str(self._record),CODE)
while True:
message = decode(self._client.recv(BUFSIZE),CODE)
if not message:
print('Client disconnected')
self._client.close()
break
else:
message=self._name +'' + \
ctime()+'\n'+message
self._record.add(message)
self._client.send(str(self._record),CODE)
HOST ='localhost'
PORT = 5000
ADDRESS = (HOST,PORT)
BUFSIZE = 1024
CODE = 'ascii'
record = ChatRecord()
server = socket(AF_INET,SOCK_STREAM)
server.bind(ADDRESS)
server.listen(5)
while True:
print ('Waiting for connection...')
client,address = server.accept()
print ('...connected from:',address)
handler = ClientHandler(client,record)
handler.start()
This is the server file
from socket import *
from codecs import decode
HOST ='localhost'
PORT = 5000
BUFSIZE = 1024
ADDRESS = (HOST,PORT)
CODE = 'ascii'
server = socket(AF_INET,SOCK_STREAM)
server.connect(ADDRESS)
print (decode(server.recv(BUFSIZE), CODE))
name = raw_input('Enter your name:')
server.send(name)
while True:
record = server.recv(BUFSIZE)
if not record:
print ('Server disconnected')
break
print (record)
message = raw_input('>')
if not message:
print ('Server disconnected')
break
server.send(message, CODE)
server.close()
This is the Chartrecord
class ChatRecord(object):
def __init__(self):
self.data=[]
def add(self,s):
self.data.append(s)
def __str__(self):
if len(self.data)==0:
return 'No messages yet!'
else:
return'\n'.join(self.data)
This is the error message I get when running the chat record. I can enter a name then after that I get the error message below
Waiting for connection...
('...connected from:', ('127.0.0.1', 51774))
Waiting for connection...
Exception in thread Thread-1:
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/threadin g.py", line 532, in __bootstrap_inner
self.run()
File "/Users/basetsanamanele/Documents/workspace/HAAAAAAAFF/ClientHandler", line 17, in run
self._client.send(str(self._record),CODE)
TypeError: an integer is required
Please assist
Edit: Also, your server isn't accepting/listing for connections
You should make the server multithreaded so that it can send and receive at the same time. Here's how it might look:
import socket
import os
from threading import Thread
import thread
def main():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host,port))
s.listen(10)
serverThreads = []
while True:
print "Server is listening for connections..."
client, address = s.accept()
serverThreads.append(Thread(target=runserver, args=(client,address)).start())
s.close()
def runserver(client, address):
clients = set()
lockClients = threading.Lock()
print ("Connection from: " + address)
with lockClients:
clients.add(client)
try:
while True:
data = client.recv(1024)
if data:
print data.decode()
with lockClients:
for c in clients:
c.sendall(data)
else:
break
finally:
with lockClients:
clients.remove(client)
client.close()
When you send a string over TCP you need to encode it to bytes. So your client file should look like this instead:
def run(self):
self._client.send(('Welcome to the chatroom!').encode())
self._name = self._client.recv(BUFSIZE).decode()
self._client.send(str(self._record),CODE)
while True:
message = self._client.recv(BUFSIZE).decode()
if not message:
print('Client disconnected')
self._client.close()
break
else:
message=self._name +'' + \
ctime()+'\n'+message
self._record.add(message)
self._client.send(self._record.encode())
I much prefer the .encode() and .decode() syntax as it makes the code a little more readable IMO.
Related
I am trying to broadcast a message to the subnet and i am giving the subnet address to the server to connect and the client throws error saying name or service unknown and not receiving the packet. Could anyone please tell me how do i broadcast message to my subnet such that client can also get that message or packet. exactly in the address area. My main doubts are about. which address is given at the client side and server side.
Error i get at client side is :
sending
Traceback (most recent call last):
File "/Threaded-server.py", line 11, in <module>
sent=s.sendto(msg.encode(),address)
socket.gaierror: [Errno -2] Name or service not known
closing socket
Process finished with exit code 1
Thanks
client
import socket
import sys
import json
connected = False
#connect to server
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((' ',10000))
connected = True
while connected == True:
#wait for server commands to do things, now we will just display things
data = client_socket.recv(1024)
cmd = json.loads(data) #we now only expect json
if(cmd['type'] == 'bet'):
bet = cmd['value']
print('betting is: '+bet)
elif (cmd['type'] == 'result'):
print('winner is: '+str(cmd['winner']))
print('payout is: '+str(cmd['payout']))
##Server
import socket, time, sys
import threading
import pprint
TCP_IP = '192.168.1.255'
TCP_PORT = 10000
BUFFER_SIZE = 1024
clientCount = 0
class server():
def __init__(self):
self.CLIENTS = []
def startServer(self):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP,TCP_PORT))
s.listen(10)
while 1:
client_socket, addr = s.accept()
print ('Connected with ' + addr[0] + ':' + str(addr[1]))
global clientCount
clientCount = clientCount+1
print (clientCount)
# register client
self.CLIENTS.append(client_socket)
threading.Thread(target=self.playerHandler, args=(client_socket,)).start()
s.close()
except socket.error as msg:
print ('Could Not Start Server Thread. Error Code : ') #+ str(msg[0]) + ' Message ' + msg[1]
sys.exit()
#client handler :one of these loops is running for each thread/player
def playerHandler(self, client_socket):
#send welcome msg to new client
client_socket.send(bytes('{"type": "bet","value": "1"}', 'UTF-8'))
while 1:
data = client_socket.recv(BUFFER_SIZE)
if not data:
break
#print ('Data : ' + repr(data) + "\n")
#data = data.decode("UTF-8")
# broadcast
for client in self.CLIENTS.values():
client.send(data)
# the connection is closed: unregister
self.CLIENTS.remove(client_socket)
#client_socket.close() #do we close the socket when the program ends? or for ea client thead?
def broadcast(self, message):
for c in self.CLIENTS:
c.send(message.encode("utf-8"))
def _broadcast(self):
for sock in self.CLIENTS:
try :
self._send(sock)
except socket.error:
sock.close() # closing the socket connection
self.CLIENTS.remove(sock) # removing the socket from the active connections list
def _send(self, sock):
# Packs the message with 4 leading bytes representing the message length
#msg = struct.pack('>I', len(msg)) + msg
# Sends the packed message
sock.send(bytes('{"type": "bet","value": "1"}', 'UTF-8'))
if __name__ == '__main__':
s = server() #create new server listening for connections
threading.Thread(target=s.startServer).start()
while 1:
s._broadcast()
pprint.pprint(s.CLIENTS)
print(len(s.CLIENTS)) #print out the number of connected clients every 5s
time.sleep(5)
I wanted to write a server which will be able to handle multiple clients sing select and threads.
I know how to write a server only with threads, or only with select. Now, I wanted to mix them together. But it seems I failed.
Server:
import threading
import socket
import select
class Client(threading.Thread):
'''
Multi-threading clients.
'''
def __init__(self):
threading.Thread.__init__(self)
pass
def setup(self, __client, __address):
self.client = __client
self.address = __address
def connect(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def run(self):
print self.client.__class__
data = self.client.recv(1024)
if data:
self.client.sendall(data)
else:
print "Error:", self.address
class Server(object):
'''
Threading server
'''
def __init__(self):
'''
Constructor
'''
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind(('127.0.0.1', 9876))
def run(self):
self.server.listen(10)
inputs = [self.server]
while 1:
inready, outready, excready = select.select(inputs, [], []);
for s in inready:
if s == self.server:
sock, address = self.server.accept();
client = Client()
client.setup(sock, address)
client.start()
self.server.close()
if __name__ == '__main__':
server = Server()
server.run()
Client:
import socket
import sys
port = 9876
size = 1024
s = None
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
s.connect(('127.0.0.1', port))
except socket.error, (value, message):
if s:
s.close()
print "Could not open socket: " + message
sys.exit(1)
while True:
data = raw_input('> ')
s.sendall(data)
data = s.recv(size)
print "Server sent: %s " % data
s.close()
Client sends and receives only one message and then Im not able to send any more messages. Why? How to improve this? Thank you.
Edit: One error found. There was a loop missing in Client's run method:
import threading import socket import select
class Client(threading.Thread):
'''
Multi-threading clients.
'''
def __init__(self):
threading.Thread.__init__(self)
pass
def setup(self, __client, __address):
self.client = __client
self.address = __address
def connect(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def run(self):
while True:
print self.client.__class__
data = self.client.recv(1024)
if data:
self.client.sendall(data)
else:
print "Error:", self.address
self.client.close()
class Server(object):
'''
Threading server
'''
def __init__(self):
'''
Constructor
'''
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind(('127.0.0.1', 9876))
def run(self):
self.server.listen(10)
inputs = [self.server]
while 1:
inready, outready, excready = select.select(inputs, [], []);
for s in inready:
if s == self.server:
sock, address = self.server.accept();
client = Client()
client.setup(sock, address)
client.start()
self.server.close()
if __name__ == '__main__':
server = Server()
server.run()
But now, when client disconnects, I have an error on server's side. How to handle this error?
Exception in thread Thread-4:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "/home/testserver.py", line 25, in run
data = self.client.recv(1024)
File "/usr/lib/python2.7/socket.py", line 174, in _dummy
raise error(EBADF, 'Bad file descriptor')
error: [Errno 9] Bad file descriptor
I try to make a chat on Python3. Here is my code:
import socket
import threading
print("Server starts working")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("", 57054))
sock.listen(2)
conn, addr = sock.accept()
def get_message():
while True:
data = sock.recv(1024).decode()
if len(data) != 0:
print("Some guy: ", data)
def send_message():
while True:
message = input()
if len(message) != 0:
message = str.encode(message)
sock.send(message)
print("You: ", message)
def run():
get_message_thread = threading.Thread(target=get_message())
send_message_thread = threading.Thread(target=send_message())
get_message_thread.daemon = True
send_message_thread.daemon = True
get_message_thread.start()
send_message_thread.start()
run()
sock.close()
But after the execution and sending a message from other client I get an error message:
Server starts working
Traceback (most recent call last):
File "/home/ptrknvk/Documents/Study/Python/chat/chat.py", line 40, in <module>
run()
File "/home/ptrknvk/Documents/Study/Python/chat/chat.py", line 30, in run
get_message_thread = threading.Thread(target=get_message())
File "/home/ptrknvk/Documents/Study/Python/chat/chat.py", line 15, in get_message
data = sock.recv(1024).decode()
OSError: [Errno 107] Transport endpoint is not connected
Process finished with exit code 1
I've read, that there are some troubles with sock.accept(), but everything's alright here, as I think.
Your program has many flaws. As zondo mentioned, you are incorrectly passing the target. They should be like threading.Thread(target=get_message). Second problem is, you should use conn (and not sock) for sending and receiving data. Third problem is, main thread was blocking at accept call and will wait for the connection. But soon as it accepts a connection, it will exit. From the main thread, you should wait for get_message_thread and send_message_thread. Try the modified code:
import socket
import threading
print("Server starts working")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("", 57054))
sock.listen(2)
conn, addr = sock.accept()
def get_message():
while True:
data = conn.recv(1024).decode()
if len(data) != 0:
print("Some guy: ", data)
def send_message():
while True:
message = input()
if len(message) != 0:
message = str.encode(message)
conn.send(message)
print("You: ", message)
def run():
get_message_thread = threading.Thread(target=get_message)
send_message_thread = threading.Thread(target=send_message)
get_message_thread.daemon = True
send_message_thread.daemon = True
get_message_thread.start()
send_message_thread.start()
get_message_thread.join()
send_message_thread.join()
run()
sock.close()
I was working on a networked chat by following a tutorial. I have two modules, chatServer.py3 and chatClient.py3. On starting the server and then a client and attempting to send a message I get the following error:
Traceback (most recent call last): File "chatClient.py3", line 49,
in <module>
Main() File "chatClient.py3", line 38, in Main
s.sendto(alias+": "+message, server)
socket.error: [Errno 57] Socket is not connected
Please keep in mind that I am a rookie and therefore I would appreciate if the solutions along with their explanations were simplistic.
chatClient.py3
import socket, time, threading
tLock = threading.Lock()
shutdown = False
def recieveing(name,sock):
locked = False
while not shutdown:
try:
tLock.aquire()
locked = True
while True:
data , addr = sock.recv(1024)
print str(data)
except:
pass
finally:
if locked:
tLock.release()
def Main():
host = '127.0.0.1'
port = 0
server = ('127.0.0.1', 5000)
s = socket.socket()
s.bind((host,port))
s.setblocking(0)
rT = threading.Thread(target=recieveing,args=("RecivedThread",s))
rT.start()
alias = raw_input("Name: ")
message = raw_input(alias+"-> ")
while message != "q":
if message != "":
s.sendto(alias+": "+message, server)
tLock.aquire()
message = raw_input(alias+"-> ")
tLock.release()
time.sleep(0.2)
shutdown = True
rT.join()
s.close()
if __name__ == '__main__':
Main()
chatServer.py3
import socket,time
host = '127.0.0.1'
port = 5000
clients = []
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host,port))
s.setblocking(0)
quitting = False
print "Server Started."
while not quitting:
try:
data, addr = s.recvfrom(1024)
if "Quit" in str(data):
quitting = True
if addr not in clients:
clients.append(addr)
print time.ctime(time.time()) + str(addr) + " : : "+str(data)
for client in clients:
s.sendto(data, client)
except:
pass
s.close()
You don't need to bind your client to the host and port. The bind command defines where the server needs to listen. The client needs to connect to the server. Like this:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server = ('127.0.0.1', 5000)
s.connect(server)
so right now in order to receive your message you need to receive one
my teachers instructions are (in the main)"Modify the loop so that it only listens for keyboard input and then sends it to the server."
I did the rest but don't understand this, ... help?
import socket
import select
import sys
import threading
'''
Purpose: Driver
parameters: none
returns: none
'''
def main():
host = 'localhost'
port = 5000
size = 1024
#open a socket to the client.
try:
clientSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSock.connect((host,port))
#exit on error
except socket.error, (value,message):
if clientSock :
clientSock.close()
print "Could not make connection: " + message
sys.exit(1)
thread1 = ClientThread()
thread1.start()
while True:
#wait for keyboard input
line = raw_input()
#send the input to the server unless its only a newline
if line != "\n":
clientSock.send(line)
#wait to get something from the server and print it
data = clientSock.recv(size)
print data
class ClientThread(threading.Thread):
'''
Purpose: the constructor
parameters: the already created and connected client socket
returns: none
'''
def __init__(self, clientSocket):
super(ClientThread, self).__init__()
self.clientSocket = clientSocket
self.stopped = False
def run(self):
while not self.stopped:
self.data = self.clientSocket.recv(1024)
print self.data
main()
I assume your purpose is to create a program that starts two threads, one (client thread) receives keyboard input and sends to the other (server thread), the server thread prints out everything it received.
Based on my assumption, you first need to start a ServerThread listen to a port (it's not like what your 'ClientThread' did). Here's an example:
import socket
import threading
def main():
host = 'localhost'
port = 5000
size = 1024
thread1 = ServerThread(host, port, size)
thread1.start()
#open a socket for client
try:
clientSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSock.connect((host,port))
except socket.error, (value,message):
if clientSock:
clientSock.close()
print "Could not connect to server: " + message
sys.exit(1)
while True:
#wait for keyboard input
line = raw_input()
#send the input to the server unless its only a newline
if line != "\n":
clientSock.send(line)
# Is server supposed to send back any response?
#data = clientSock.recv(size)
#print data
if line == "Quit":
clientSock.close()
break
class ServerThread(threading.Thread):
def __init__(self, host, port, size):
super(ServerThread, self).__init__()
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.bind((host, port))
self.sock.listen(1)
self.data_size = size
self.stopped = False
def run(self):
conn, addr = self.sock.accept()
print 'Connected by', addr
while not self.stopped:
data = conn.recv(self.data_size)
if data == 'Quit':
print 'Client close the connection'
self.stopped = True
else:
print 'Server received data:', data
# Is server supposed to send back any response?
#conn.sendall('Server received data: ' + data)
conn.close()
if __name__ == '__main__':
main()
And these are the output:
Connected by ('127.0.0.1', 41153)
abc
Server received data: abc
def
Server received data: def
Quit
Client close the connection
You may check here for more details about Python socket: https://docs.python.org/2/library/socket.html?#example