I wanted to make a server and a client with Python.
It was supposed to make multiple connections, one, where the server is sending something to the client, and one where the client is sending something to the server.
The first connection worked fine, but the second one crashed with the message:
socket.error: [Errno 9] Bad file descriptor
Here is the Server:
import socket
import errno
import pickle
def Main():
host = '188.174.233.99'
port = 66666
all_text = ['text1', 'text2', 'text3']
all_description = ['Test \n Description1\n', 'Test \n Description1\n', 'Test \n Description1\n']
all_images = ['unlock.png', 'unlock.png', 'unlock.png']
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
s.bind((host, port))
s.listen(1)
while True:
c, addr = s.accept()
c.setblocking(0)
print "Connection from: " + str(addr)
command = c.recv(1024)
if command == 'GIVEALL':
textstring = pickle.dumps([all_text, all_images, all_description])#verwandelt Liste in String
c.send(textstring)
else:
try:
new_event = pickle.loads(command)
print new_event
caption = new_event[0]
image = new_event[1]
describtion = new_event[2]
city = new_event[3]
except:
pass
try:
c.close()
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
except socket.error as e:
if e.errno != errno.ECONNRESET:
raise
pass
if __name__ == '__main__':
Main()
And here is the Client:
import socket
import pickle
from kivy.properties import StringProperty
from kivy.properties import NumericProperty
from kivy.properties import ListProperty
class Netclient(object):
def __init__(self):
self.s = socket.socket()
self.texte = []
self.current = 'All'
self.ip = '188.174.233.99'
self.port = 66666
def giveWid(self):
print 'give Widgets executed'
if self.current == 'All':
self.texte, self.images, self.description = self.sentHOT(self.ip, self.port)
return self.texte, self.images, self.description
def sentHOT(self, host, port):
self.s.connect((host, port))
self.s.send('GIVEALL')#sends command
recived_string = self.s.recv(1023)
more_text = pickle.loads(recived_string)#verwandelt string in liste
self.s.close()
print 'closed'
return more_text[0], more_text[1], more_text[2]
def add_event(self, caption, image, description, city='Pawonkow'):
new_event = [caption, image, description, city]
new_compact_event = pickle.dumps(new_event)
self.s.connect((self.ip, self.port))
self.s.send(new_compact_event)
self.s.close()
n = Netclient()
t, i, d = n.giveWid()
print t
n.add_event('new', 'new.png', 'ew event', 'Hanau')
The reason is that you are trying to reconnect a closed socket. You have to either create a new socket or reuse the old one as long as it's connected.
In method def sentHOT(...): comment the line self.s.close() and in method def add_event(...) comment the line self.s.connect((self.ip, self.port)) then should work. Further, please take a look at this tutorial, it helps you with socket programming.
Related
This program has both the ChatServer class and ChatClient class in the same file, and should be called in the terminal by --name=server --port=8800 for the server and --name=client1 --port=8800 for the client. The problem comes from the client class not being able to complete a try:
When running the program with server name, it seems to work fine. When it runs with client name, I get the output Failed to connect to chat server # port 8800.
You can find where this except statement lies.
import select
import socket
import sys
import signal
import _pickle as cPickle
import struct
import argparse
SERVER_HOST = 'localhost'
CHAT_SERVER_NAME = 'server'
# Some utilities
def send(channel, *args):
buffer = cPickle.dumps(args)
value = socket.htonl(len(buffer))
size = struct.pack("L", value)
channel.send(size)
channel.send(buffer)
def receive(channel):
size = struct.calcsize("L")
size = channel.recv(size)
try:
size = socket.ntohl(struct.unpack("L", size)[0])
except struct.error as e:
return ''
buf = ""
while len(buf) < size:
buf = channel.recv(size - len(buf))
return cPickle.loads(buf)[0]
class ChatServer(object):
def __init__(self, port, backlog=5):
self.clients = 0
self.clientmap = {}
self.outputs = []
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Enable re-using socket address
self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server.bind((SERVER_HOST, port))
print('Server listening to port: %s...' % port)
self.server.listen(backlog)
# Catch keyboard interrupts
signal.signal(signal.SIGINT, self.sighandler)
def sighandler(self, signum, frame):
# Close the server
print("Shutting down server...")
# Close existing client sockets
for output in self.outputs:
output.close()
self.server.close()
def get_client_name(self,client):
info = self.clientmap[client]
host, name = info[0][0], info[1]
return '#'.join((name, host))
def run(self):
inputs = [self.server, sys.stdin]
self.outputs = []
running = True
while running:
try:
readable, writeable, exceptional = select.select(inputs, self.outputs, [])
except select.error as e:
break
for sock in readable:
if sock == self.server:
# handle the server socket
client, address = self.server.accept()
print("Chat Server: got connection %d from %s" % (client.fileno(), address))
# Read the login name
cname = receive(client).split('NAME: ')[1]
# Compute client name ad send back
self.clients += 1
send(client, 'CLIENT: ' + str(address[0]))
inputs.append(client)
self.clientmap[client] = (address, cname)
# Send joining information to other clients
msg = "\n(Connected: New client (%d) from %s)" % (self.clients, self.get_client_name(client))
for output in self.outputs:
send(output, msg)
self.outputs.append(client)
elif sock == sys.stdin:
# Handle standard input
junk = sys.stdin.readline()
running = False
else:
# Handle all other sockets
try:
data = receive(sock)
if data:
# Send as new client's message..
msg = '\n[' + self.get_client_name(sock) + ']>>' + data
# Send data to all except ourself
for output in self.outputs:
if output != sock:
send(output, msg)
else:
print("Chat server: %d hung up" % sock.fileno())
self.clients -= 1
sock.close()
inputs.remove(sock)
self.outputs.remove(sock)
# Sending client leaving info to others
msg = "\n(Now hung up: Client from %s" % self.get_client_name(sock)
for output in self.outputs:
send(output, msg)
except socket.error as e:
# Remove
inputs.remove(sock)
self.outputs.remove(sock)
self.server.close()
class ChatClient(object):
def __init__(self, name, port, host=SERVER_HOST):
self.name = name
self.connected = False
self.host = host
self.port = port
# Initial Prompt
self.prompt = '[' + '#'.join((name, socket.gethostname().split('.')[0])) + ']> '
# Connect to server at port
try:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((host, self.port))
print("Now connected to chat server# port %d" % self.port)
self.connected = True
# Send by name...
send(self.sock, 'NAME: ' + self.name)
data = receive(self.sock)
# Contains client address, set it
addr = data.split('CLIENT: ')[1]
self.prompt = '[' + '#'.join((self.name, addr)) + ']>'
except socket.error as e:
print("Failed to connect to chat server # port %d" % self.port)
sys.exit(1)
def run(self):
while self.connected:
try:
sys.stdout.write(self.prompt)
sys.stdout.flush()
# Wait for input from stdin and socket
readable, writable, exceptional = select.select([0, self.sock], [], [])
for sock in readable:
if sock == 0:
data = sys.stdin.readline().strip()
if data:
send(self.sock, data)
elif sock == self.sock:
data = receive(self.sock)
if not data:
print('Client shutting down')
self.connected = False
break
else:
sys.stdout.write(data + '\n')
sys.stdout.flush()
except KeyboardInterrupt:
print("Client interrupted")
self.sock.close()
break
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Socket Server Example with Select')
parser.add_argument('--name', action="store", dest="name", required=True)
parser.add_argument('--port', action="store", dest="port", type=int, required=True)
given_args = parser.parse_args()
port = given_args.port
name = given_args.name
if name == CHAT_SERVER_NAME:
server = ChatServer(port)
server.run()
else:
client = ChatClient(name=name, port=port)
client.run()
Server.py
from twisted.internet import protocol, reactor
import names
COLORS = [
'\033[31m', # RED
'\033[32m', # GREEN
'\033[33m', # YELLOW
'\033[34m', # BLUE
'\033[35m', # MAGENTA
'\033[36m', # CYAN
'\033[37m', # WHITE
'\033[4m', # UNDERLINE
]
transports = set()
users = set()
class Chat(protocol.Protocol):
def connectionMade(self):
name = names.get_first_name()
color = COLORS[len(users) % len(COLORS)]
users.add(name)
transports.add(self.transport)
self.transport.write(f'{color}{name}\033[0m'.encode())
def dataReceived(self, data):
for t in transports:
if self.transport is not t:
t.write(data)
class ChatFactory(protocol.Factory):
def buildProtocol(self, addr):
return Chat()
print('Server started!')
reactor.listenTCP(8000, ChatFactory())
reactor.run()
Client.py
import socket
import select
import sys
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 8000))
name = None
while True:
read, write, fail = select.select((s, sys.stdin), (), ())
for desc in read:
if desc == s:
data = s.recv(4096)
print(data.decode())
if name is None:
name = data.decode()
s.send(f'{name} is connected!'.encode())
else:
msg = desc.readline()
msg = msg.replace('\n', '')
s.send(f'{name} {msg}'.encode())
Server.py file has no errors, but when I run the Client.py
I get an error. I searched this problem in google, but I have no luck.
when I run client.py
I get error like this :
read, write, fail = select.select((s, sys.stdin), (), ())
OSError: [WinError 10038]
Any suggestion??
I think sys.stdin is giving the error.
I have made some changes to code, try this one:
import socket
import select
import sys
host='127.0.0.1'
port=8000
backlog=5
size=1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(backlog)
name = None
input=[s]
while True:
read, write, fail = select.select(input, (), ())
for desc in read:
if desc == s:
data = s.recv(4096)
print(data.decode())
if name is None:
name = data.decode()
s.send(f'{name} is connected!'.encode())
else:
msg = desc.readline()
msg = msg.replace('\n', '')
s.send(f'{name} {msg}'.encode())
https://stackoverflow.com/questions/10842428/can-select-be-used-with-files-in-python-under-windows this question may give you more information.
I wanted to make a more complex server in Python, reciving lists of commands and returning lists of values, so I can send more unsing a socket.
Sometimes it works, and sometimes it crashes, and as I am new to socket programming, I have no explnation why this is the case?
Here is the Server:
import socket
import errno
import pickle
def Main():
host = '192.168.43.121'
port = 12345
all_text = ['text1', 'text2', 'text3']
music_text = ['Konzert1', 'Konzert2', 'Konzert3']
all_description = ['Test \n Description1\n', 'Test \n Description1\n', 'Test \n Description1\n']
all_images = ['unlock.png', 'unlock.png', 'unlock.png']
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
s.bind((host, port))
s.listen(1)
while True:
c, addr = s.accept()
c.setblocking(0)
print "Connection from: " + str(addr)
pcommand = c.recv(1024)
command = pickle.loads(pcommand)
if command[0] == 'GIVEALL':
textstring = pickle.dumps([all_text, all_images, all_description])#verwandelt Liste in String
c.send(textstring)
elif command[0] == 'GIVEMUSIC':
textstring = pickle.dumps([music_text, all_images, all_description])#verwandelt Liste in String
c.send(textstring)
elif command[0] == 'ADD':
try:
new_event = pickle.loads(command)
print new_event
caption = command[1]
image = command[2]
describtion = command[3]
city = command[4]
#add to SQL
except:
pass
try:
c.close()
#s.setsockopt(socket.AF_INET, socket.SOCK_STREAM, 1)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
except socket.error as e:
if e.errno != errno.ECONNRESET:
raise
pass
if __name__ == '__main__':
Main()
And Here is the Client:
import socket
import pickle
from kivy.properties import StringProperty
from kivy.properties import NumericProperty
from kivy.properties import ListProperty
class Netclient(object):
def __init__(self):
self.texte = []
self.current = 'All'
self.city = 'Pawonkuw'
self.ip = '192.168.43.121'
self.port = 12345
def giveWid(self):
print 'give Widgets executed'
if self.current == 'All':
self.texte, self.images, self.description = self.sentHOT(self.ip, self.port)
elif self.current == 'Music':
self.texte, self.images, self.description = self.sentMusic(self.ip, self.port)
return self.texte, self.images, self.description
def sentHOT(self, host, port):
self.s = socket.socket()
#print self.current
self.s.connect((host, port))
command = ['GIVEALL', self.city]
pcommand = pickle.dumps(command)
self.s.send(pcommand)#sends command
recived_string = self.s.recv(1023)
more_text = pickle.loads(recived_string)#verwandelt string in liste
self.s.close()
#print 'closed'
return more_text[0], more_text[1], more_text[2]
def sentMusic(self, host, port):
self.s = socket.socket()
self.s.connect((host, port))
command = ['GIVEMUSIC', self.city]
pcommand = pickle.dumps(command)
self.s.send(pcommand)#sends command
recived_string = self.s.recv(1023)
more_text = pickle.loads(recived_string)#verwandelt string in liste
self.s.close()
self.images = ['unlock.png', 'unlock.png', 'unlock.png']
#print more_text[0]
return more_text[0], more_text[1], more_text[2]
def add_event(self, caption, image, description, city='Pawonkow'):
self.s = socket.socket()
self.s.connect((self.ip, self.port))
new_event = ['ADD', caption, image, description, self.city]
new_compact_event = pickle.dumps(new_event)
self.s.send(new_compact_event)
self.s.close()
n = Netclient()
t, i, d = n.giveWid()
print t
n.add_event('new', 'new.png', 'ew event', 'Hanau')
t, i, d = n.giveWid
And here is the full traceback:
Connection from: ('192.168.43.121', 43169)
Connection from: ('192.168.43.121', 43170)
Traceback (most recent call last):
File "server2.py", line 61, in <module>
Main()
File "server2.py", line 28, in Main
pcommand = c.recv(1024)
socket.error: [Errno 11] Resource temporarily unavailable
Please Help
Ok, I solved it, the Problem was in the server, I needed to handle the error, by adding a try and except:
import socket
import errno
import pickle
def Main():
host = 'localhost'
port = 12345
all_text = ['text1', 'text2', 'text3']
music_text = ['Konzert1', 'Konzert2', 'Konzert3']
all_description = ['Test \n Description1\n', 'Test \n Description1\n', 'Test \n Description1\n']
all_images = ['unlock.png', 'unlock.png', 'unlock.png']
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
s.bind((host, port))
s.listen(1)
while True:
c, addr = s.accept()
c.setblocking(0)
print "Connection from: " + str(addr)
try:
pcommand = c.recv(2048) # here was the error
except IOError as e: # and here it is handeled
if e.errno == errno.EWOULDBLOCK:
pass
command = pickle.loads(pcommand)
if command[0] == 'GIVEALL':
textstring = pickle.dumps([all_text, all_images, all_description])#verwandelt Liste in String
c.send(textstring)
elif command[0] == 'GIVEMUSIC':
textstring = pickle.dumps([music_text, all_images, all_description])#verwandelt Liste in String
c.send(textstring)
elif command[0] == 'ADD':
try:
new_event = pickle.loads(command)
print new_event
caption = command[1]
image = command[2]
describtion = command[3]
city = command[4]
#add to SQL
except:
pass
try:
c.close()
#s.setsockopt(socket.AF_INET, socket.SOCK_STREAM, 1)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
except socket.error as e:
if e.errno != errno.ECONNRESET:
raise
pass
if __name__ == '__main__':
Main()
I have a Multihtreaded Server with python that can handle clients request, but i have a problem with this.
In my Server Class I have a start function that start listening to clients like this:
class Server:
def __init__(self, clients={}):
self.clients = clients
self.ip = 'localhost'
self.port = ****
self.pattern = '(C\d)'
def start(self):
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.s.bind((self.ip, self.port))
self.s.listen(10)
while 1:
clientsock, addr = self.s.accept()
print ('Connected with ' + addr[0] + ':' + str(addr[1]))
_thread.start_new_thread(self.handler, (clientsock, addr))
def handler(self, clientsock, addr):
data = clientsock.recv(BUFF)
print ('Data : ' + repr(data))
data = data.decode("UTF-8")
result = re.match(self.pattern, data)
print (data)
if(result):
self.registerClient(clientsock, data)
if(data == "Exit"):
self.exitClient(clientsock)
def server_response(self, message, flag, err):
if(flag):
res = message.encode('utf-8')
return res
else:
res = message.encode('utf-8')+ "[ ".encode('utf-8')+err.encode('utf-8')+ " ]".encode('utf-8')
return res
def registerClient(self, clientsock, data):
if(data in self.clients):
err = "Error : Client Name Exist!"
clientsock.send(self.server_response('Reg#NOK#', 0, err))
clientsock.close()
sys.exit(1)
self.clients[clientsock] = data
clientsock.send(self.server_response('Reg#OK', 1, ''))
def exitClient(self, clientsock):
try:
f = self.clients.pop(clientsock)
clientsock.send(self.server_response('BYE#OK', 1, ''))
clientsock.close()
except KeyError:
err = "Error : Client Doesn't Connected To Server!"
clientsock.send(self.server_response('BYE#NOK#', 0, err))
clientsock.close()
sys.exit(1)
And this is my client Class:
class Client:
def __init__(self, name):
self.name = name
self.ip = '127.0.0.1'
self.next_client = None
self.s = ""
try:
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print ('Reg#NOK#[ ' + msg[1] + ' ]')
sys.exit()
def register(self, server):
self.s.connect((server.ip, server.port))
message = self.name
try:
self.s.sendall(bytes(message, 'UTF-8'))
except (socket.error):
print ('Send Failed')
sys.exit()
reply = self.s.recv(4096)
print ("Respose From Server : " + reply.decode("utf-8") )
def exitFromServer(self, server):
message = "Exit".encode('utf-8')
try:
a = self.s.sendall(message)
except (socket.error):
print ('Send Failed')
sys.exit()
reply = self.s.recv(4096)
And this is the main file:
from server import *
from client import *
import _thread
a = Server()
_thread.start_new_thread(a.start, ())
b = Client("C1")
b.register(a)
b.exitFromServer(a)
As you can see when start function from Server class called there is no thread that can handle create Client , I mean when I use start function like this with out thread there is no way that program can go ahead in main file , I know I should use another thread here but where and how, I use Python 3.4, Thanks for helping me.
Edit
the Problem with start was Solved , Thanks from tdelaney,
but when I run this only the register function works and exitFromServer dont do anything can you tell me where is the problem.the program dosent do anything after execute register function and it seems that its wating for something.
This mean?
import threading
from server import *
from client import *
global a
a = Server()
def sServer():
global a
a.start()
def cClient():
global a
b = Client("C1")
b.register(a)
s = threading.Thread(name='server', target=sServer)
c = threading.Thread(name='client', target=cClient)
s.start()
c.start()
In Server Class I must add another while True loop after handler function cause it shuould do all client request till client has request:
def handler(self, clientsock, addr):
while 1:
data = clientsock.recv(BUFF)
print ('Data : ' + repr(data))
data = data.decode("UTF-8")
result = re.match(self.pattern, data)
if(result):
self.registerClient(clientsock, data)
if(data == "Exit"):
self.exitClient(clientsock)
break
I am building a chat server client system. a socket is created at the client side to connect to the server listening at a port. The problem is when I try to close the socket from the client side, the asyncore handle_close does not detect it.
Server code:
clients = {}
identity={}
class MainServerSocket(asyncore.dispatcher):
def __init__(self, port):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.bind(('',port))
self.listen(5)
def handle_accept(self):
newSocket, address = self.accept( )
clients[address] = newSocket
#try :
#hndl=newSocket.recv(1024)
#print "Connected from", address,hndl
#except :
#e = sys.exc_info()[1]
print "Connected from", address
handler=SecondaryServerSocket(newSocket)
handler.setAddr(address)
every = clients.values()
for one in every:
one.send('Server message:'+str(address)+' joined'+'\n')
class SecondaryServerSocket(asyncore.dispatcher_with_send):
def setAddr(self, addr):
self.addr = addr
def isid(self,txt):
pattern=re.compile('\*\$\$\$\*(.+)\*\$\$\$\*')
match=pattern.search(txt)
rv=0
if match :
self.hndl=match.group(1)
rv=1
if self.hndl not in identity.values():
identity[self.addr]=self.hndl
every=clients.values()
for one in every:
one.send('Server message:'+str(self.addr)+' is known as '+self.hndl+'\n')
else:
clients[self.addr].send("Server message: handle in use, retry. Disconnecting.")
self.close()
return rv #del clients[self.addr]
def handle_read(self):
receivedData = self.recv(8192)
if receivedData:
if not self.isid(receivedData):
#self.addr
every = clients.values()
for one in every:
one.send(receivedData)
else: self.close( )
def handle_close(self):
print "Disconnected from", self.getpeername( )
one = self.getpeername( )
del identity[one]
del clients[one]
every=clients.values()
try:
for one in every:
one.send('server message:'+str(self.addr)+' quit'+'\n')
except: pass
print "server started"
MainServerSocket(21567)
asyncore.loop( )
client code(relevant bits):
class Application(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.serv_ip=StringVar()
self.port=StringVar()
self.handle=StringVar()
self.serv_ip.set('127.0.0.1')
self.port.set('21567')
self.grid()
self.create_widgets()
self.lastname=""
self.currentname=""
self.delim=('-'*45)+'\n'
def connect(self):
if len(self.handle.get())>0 and not self.handle.get().isspace() :
HOST = self.serv_ip.get()
PORT = int(self.port.get())
#BUFSIZE = 1024
ADDR = (HOST, PORT)
try:
self.tcpCliSock = socket(AF_INET, SOCK_STREAM)
self.tcpCliSock.connect(ADDR)
idtext='*$$$*'+self.handle.get()+'*$$$*'
self.tcpCliSock.send(idtext)
self.add("sys message: CONNECTED TO "+str(HOST)+':'+str(PORT)+'\n')
self.socket()
self.con_button.configure(text="DISCONNECT!",command=self.disconnect)
self.entry_field.configure(state=NORMAL)
self.handle_entry.configure(state=DISABLED)
except:
e = sys.exc_info()[1]
self.add("sys message: ERROR CONNECTING to "+str(HOST)+':'+str(PORT)+" "+str(e)+'\n')
#pass
else : self.add("sys message: Enter handle/nickname and try again."+'\n')
def disconnect(self):
#try : self.tcpCliSock.shutdown(2)
#except: pass
#self.tcpCliSock.close()
self.tcpCliSock.send('')
self.tcpCliSock.close()
self.closeflag=1
self.add("sys message: Disconnected."+'\n')
self.con_button.configure(text="CONNECT!",command=self.connect)
self.entry_field.configure(state=DISABLED)
self.handle_entry.configure(state=NORMAL)
self.closeflag=0
#self.send_button.configure(state=DISABLED)
def socket(self):
def loop0():
while 1:
try:
if self.closeflag==0:
data = self.tcpCliSock.recv(BUFSIZE)
if data: self.add(data)
except:
e = sys.exc_info()[1]
self.add("ERROR: "+str(e)+' disconnecting...'+'\n')
self.con_button.configure(text="CONNECT!",command=self.connect)
self.entry_field.configure(state=DISABLED)
self.handle_entry.configure(state=NORMAL)
self.closeflag=0
thread.exit()
#self.disconnect()
break
if self.closeflag==1 :
self.tcpCliSock.close()
print "ping"
thread.exit()
thread.start_new_thread(loop0, ())
I know this is a lot of code but I am not sure which bit is causing the problems so decided to add all the parts I think could be responsible.when the disconnect function is called, the server doesnt detect a disconnection. And then after the disconnect, the connect function is called, then the client crashes.