I am pretty new at this.I am trying to build a server(chat server)
Sorry for presenting such a messing code.
There are alot of things that i am going to change about this code.
but as of now i just need help with one thing:
when i start let say more then one cleints on this ...and then just close the client i get this message:
Unhandled exception in thread started by
i have tryed to kill the thread as you can see in many places in this code. but i don't know what i am doing wrong ..
i am new at this.
any syggestions on what i should do ?
#encoding: utf-8
import socket, random, time, thread, errno, traceback
print socket.gethostname()
print "current machines IP address: "+socket.gethostbyname(socket.gethostname())
host ="10.0.0.1"# raw_input("IP: ")
# = socket.gethostbyname(socket.gethostname())
port = 12345
print host
conn_list =[None]*10
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host, port))
sock.listen(10)
print "connected..\n\n\n\n"
def recv(conn):
while True:
try:
message = conn.recv(1024)
if "MESG" == message[1:5]:
message = message[6:].split(':')
name = str(conn)
conn_number = conn_list.index(conn)
conn_name = str(conn_number)
message = message[2]
reciever = message[0:1]
reciever = int(reciever)
for conn in conn_list:
if reciever == conn_list.index(conn):
conn.send(message)
print "Connection "+conn_name+" -----> "+str(reciever)+" :"+message+"\n"
#conn = findTheRightConnection(conn_list, conn_number)
break
else:
pass
except ValueError:
print "ValueError by %s" % (str(conn))
print conn.send("\nOpps you are not typing the correct connection number infront your message!")
except IOError:
bye(conn,conn_list)
print"Going to try to kill the thread here "
thread.quit()
thread.isAlive()
print "Still alive..."
except socket.error, v:
errorcode=v[0]
bye(conn,conn_list)
print"Going to try to kill the thread or here"
thread.quit()
thread.isAlive()
print "Still alive..."
except Exception, e:
traceback.print_exc()
finally:
thread.isAlive()
print"\nChanging the conn back to what it was... "
conn = findTheRightConnection(conn_list, conn_number)
def handle_connection(conn):
try:
recv(conn)
except socket.error, v:
errorcode=v[104]
bye(conn)
def bye(conn,conn_list):
i= 0
print "bye"
connectionName = str(conn_list.index(conn))
conn.close
conn_list = conn_list
print conn_list
for element in conn_list:
if element == conn:
conn_list[i] = None
break
i += i
print "Connection number "+connectionName+" is terminated"
print conn_list
return "Connection Terminated"
def welcome(conn,conn_list):
i = 0
for element in conn_list:
if element == None:
conn_list[i] = conn
print "Connection added in the conn_list on the slot %d" % (i)
print conn_list
return conn_list
else:
i = i+1
pass
print "The server if full! No more space left"
return conn_list
def findTheRightConnection(conn_list, number):
for conn in conn_list:
if number == conn_list.index(conn):
return conn
else:
pass
print "\nSomthing went wrong while trying to find the right connection in the method findTheRightConnection()"
return
while True:
conn, addr = sock.accept()
conn_list = welcome(conn,conn_list)
print "Got connection from : "+str(addr[0])+" by connection number: "+str(conn_list.index(conn))+"\n\n\n\n"
msg = "Welcome to the server!"
conn.send(":INFO:"+str(int(time.time()))+":"+str(len(msg))+":"+msg)
thread.start_new_thread(handle_connection, (conn,))
If you are still having trouble creating a instant messaging program in Python, you might be interested in this answer to another question.
Simple_Server.py is a minimal server implementation. A far more complex server with a variety of features can be provided on request. The complex server supports authentication, friends, private messaging, channels, filters, math evaluation, and admin controls.
MultichatClient.py is a port of a Java program written by a teacher from a networking class. The program must be run from the command line, and it must be given the server as an argument. You can use either the server's name on the network or its IP address.
Simple_Client.pyw is a more complicated client that does not require being started from the command line. When it starts, it will ask for server's name and try connecting to it while showing a progress dialog. The program will automatically try logging any errors to a file.
affinity.py is required for threadbox.py to run. (runs code on a specific thread regardless of origin)
threadbox.py is required for safetkinter.py to run. (metaclass clones classes to run using affinity)
safetkinter.py is required for Simple_Client.pyw to run. (makes tkinter safe to use with threads)
Related
I know there is a lot of post with titles similar to this one. Most of them have no answers or just answer how to respond to one client not multiple. Ive been bashing my head for sometime with this code. I know for sure that recieving connections and adding them to a list is working. My problem is when I try to print messages from the clients o screen. One client works fine, you can his messages on screen, the problem comes whith more than one client. When the second client connects you cant see his messages on the server side, after some messages from the first client, the messages sent from the second client appear. So I know for sure the messages are being recieved, the problem is with the printing.
server script:
import socket,sys
from threading import Thread
prevcon=0
buffsize=1024
connections=[]
addreses=[]
try:
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
except socket.error as e:
print ("Failed to create a socket")
print (e)
host="192.168.0.103"#raw_input("Enter Target host here: ")
port=12345#raw_input("Enter Target port here: ")
try:
s.bind((host,int(port)))
except socket.error as e:
print ("Failed to Connect")
print (e)
s.listen(5)
s.setsockopt( socket.SOL_SOCKET,
socket.SO_REUSEADDR, 1 )
def listen_connections():
while True:
#print ("waiting for connection")
client_sock, addr = s.accept()
connections.append(client_sock)
addreses.append(addr)
print ("client connected from: ",addr)
def print_messages():
while True:
for i in range(0,len(connections)):
try:
data=connections[i].recv(buffsize)
except socket.error:
print ("User Disconnected from: ",connections[i])
connections[i].close()
del connections[i]
del addreses[i]
continue
print (data.decode("utf-8"))
print (connections)
#send_message(data,i)
s.close()
def send_message(data,pos):
for connection in connections:
if connection!=connections[pos]:
connection.send(data)
if __name__=="__main__":
thread1=Thread(target=listen_connections)
thread2=Thread(target=print_messages)
thread1.daemon=True
thread2.daemon=True
thread1.start()
thread2.start()
client script:
import socket,sys
from threading import Thread
try:
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
except socket.error as e:
print ("Failed to create a socket")
print e
host="192.168.0.103"#raw_input("Enter Target host here: ")
port=12345#raw_input("Enter Target port here: ")
try:
s.connect((host,int(port)))
except socket.error as e:
print "Error Connecting"
print e
print ("Connected to host: %s and port: %s" %(host,port))
def leer():
while True:
data=s.recv(1024)
print data.decode("utf-8")
def send():
while True:
payload=raw_input("Enter here text to send: ")
s.send(payload)
if __name__=="__main__":
t1=Thread(target=leer)
t2=Thread(target=send)
t1.daemon=True
t2.daemon=True
t1.start()
t2.start()
I have a server-client application written in python. Everything worked fine but I wanted to make the server multi threaded and everything crashed.
Here is part of the code for the server:
host = 'localhost'
port = 10001
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
class ClientThread(threading.Thread):
def __init__(self, ip, port, socket):
print '5'
threading.Thread.__init__(self)
self.ip = ip
self.port = port
self.socket = socket
print "[+] New thread started for "+ip+":"+str(port)
def __run__(self):
while True:
try:
#conn, addr = sock.accept()
print >>sys.stderr, "Connection from : "+ip+":"+str(port)
print '6'
#reqCommand = conn.recv(1024)
reqCommand = self.recv(1024)
print '7'
command = reqCommand.split(' ', 1) # get <<filename>>
print '8'
reqFile = command[1] # takes the name of the file
reqCommand = command[0]
print '9'
encFile = reqFile + "_enc"
print >>sys.stderr, 'Client> %s' % (reqCommand)
if (reqCommand == 'get'):
pass
try:
os.remove(encFile) # removes the encrypted file
except OSError, e:
print ("Error: %s - %s." % (e.filename,e.strerror))
print >>sys.stderr, 'successfully finished'
print >>sys.stderr, 'waiting for new connections...'
finally:
# clean up connection
self.close()
while True:
sock.listen(4)
print "\nListening for incoming connections..."
(conn, (ip, port)) = sock.accept()
print '1'
newthread = ClientThread(ip, port, conn)
print '2'
newthread.start()
print '3'
threads.append(newthread)
print '4'
When I type in the client: "get " it sends the message to the client but it doesn't receive anything back. In the server as you can see I have a lot of prints to see where it crashes. It prints in the following order: 1 5 2 3 4. + it also prints [+] new thread...
As you can also see I've used self.recv instead of conn.recv (this was a solution that I found on stackoverflow, but it didn't work)
Does anyone have a clue what I'm doing wrong? I mention again that before I've added threads and the class ClientThread everything worked fine. Thanks in advance!
You have a lot of errors in the code shown.
E.g. self.recv(1024) should probably be replaced with self.socket.recv(1024), and self.close() with self.socket.close()? (since self is an instance of ClientThread/Thread, not a socket).
I also think run method should be named just run (not __run__), and if you do a close() in the finally in run() the second time while True is executed connction will be already closed.
In addition to that, large chunks are missing, e.g. all the imports, and a call to bind() - e.g. something like sock.bind((socket.gethostname(), port))
Other than that and assuming all these errors are fixed, it seems that it should do what it is supposed to.
I am new to python and I am currently working on a chat room program in Python (still in progress...). I have also made a GUI for my program. Initially, I made two py files, one for the GUI and one for the chatting function. They both worked perfectly when separated. After, I combined the two files. I faced the following two problems:
One of my threads (target = loadMsg) is used to wait for the host's msg and print it out on the screen. The problem is that it delays for one msg every time. For example, I sent a "1" to the host and the host should return a "1" immediately. But, the "1" I received didn't appear on my screen. Then I send a "2" to the host and the host should reply a "2" immediately. Then, my screen shows a "1" but the "2" is still missing until the host reply a "3" to me, after I send a "3" to the host. Where is the problem?
This is a technical problem. I was testing the stability of the chat room and I found that about 10% of my msg disappeared during the transmission and this situation occurs randomly. How can I fix such a problem?
Sorry for my poor English. I hope someone can help me with it.T_T
Here is my code for your reference:
---Client
import pygtk,gtk
import logging
from threading import *
import socket
DEBUG = 1
HOST = ''
PORT = 8018
TIMEOUT = 5
BUF_SIZE = 1024
class Base():
def reload(self):
try:
buf = self.sock.recv(BUF_SIZE)
print buf
self.addMsg(buf)
except:
pass
def reload_butt(self,widget):
try:
self.thread = Thread(target=self.reload)
self.thread.start()
except:
pass
def loadMsg(self):
try:
while True :
buf = self.sock.recv(BUF_SIZE)
print buf
self.addMsg(buf)
except:
self.sock.close()
def sendMsg(self,widget):
if DEBUG : print "Send Msg"
if self.entry.get_text() : self.sock.send(self.entry.get_text())
self.entry.set_text("")
def addMsg(self,string):
if DEBUG : print "Try to add Msg"
if self.entry.get_text() :
iter = self.buffer1.get_iter_at_offset(-1)
self.buffer1.insert(iter,("\n Username: "+string))
self.entry.set_text("")
self.adj = self.scrolled_window.get_vadjustment()
self.adj.set_value( self.adj.upper - self.adj.page_size )
if DEBUG : print "Add msg ok"
def destroy(self,widget):
if DEBUG : print "Destroy function called"
self.sock.close()
gtk.main_quit()
def __init__(self,sock):
if DEBUG : print "Initializing..."
self.sock = sock
self.win=gtk.Window()
self.win.connect("destroy",self.destroy)
self.vbox=gtk.VBox()
self.win.add(self.vbox)
self.view=gtk.TextView()
self.view.set_editable(False)
self.buffer1=self.view.get_buffer()
self.scrolled_window=gtk.ScrolledWindow()
self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
self.scrolled_window.add(self.view)
self.vbox.add(self.scrolled_window)
self.entry=gtk.Entry()
self.entry.connect("activate",self.sendMsg)
self.enter=gtk.Button("Enter")
self.enter.connect("clicked",self.sendMsg)
self.reload=gtk.Button("Reload")
self.reload.connect("clicked",self.reload_butt)
self.hbox=gtk.HBox()
self.hbox.add(self.entry)
self.hbox.pack_start(self.reload,False,False)
self.hbox.pack_start(self.enter,False,False)
self.vbox.pack_start(self.hbox,False,False)
self.win.show_all()
if DEBUG : print "Finish initializing"
def main(self):
try :
gtk.main()
except :
print "Error!!!"
def main() :
try :
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))
print ('Connecting to '+ str(HOST) +' ' + str(PORT))
base=Base(sock)
thread1=Thread(target=base.loadMsg)
thread2=Thread(target=base.main)
thread2.start()
thread1.start()
except :
print "Err0r!!!"
sock.close()
main()
---host (an echo host)
import socket
HOST = ''
PORT = 8018
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)
conn, addr = s.accept()
print 'Connected by', addr
try :
print "Start!"
while True:
data = conn.recv(1024)
print data
reply = data # echo
if not reply : break
if reply== "!q" :
conn.close()
break
conn.send(reply)
conn.close()
except :
print "Error!!!!!"
conn.close()
I would seriously recommend to use the gio library (part of glib). Using that library, you connect functions to the socket operations such as when data is available, or when data can be written to the socket. The library will call these function when necessary, and you don't need a wait loop. Which is more CPU-friendly.
http://jcoppens.com/soft/howto/gtk/chat_socket.php contains an example of communications between a C program and Python, using gio, which might be useful to you.
This way, you can start monitoring the sockets after the GUI has started, and you do not need threads to attend the communications.
I need use port forwarding in Python to communicate with a remote MySQL DB through an SSH tunnel. I downloaded the paramiko package and tried out the port forwarding demo (forward.py). It works very nicely, but I am having trouble integrating it into my own scripts (similar to the one below). When the main forwarding function is called it enters an infinite loop and the rest of my code does not execute. How can I use the forward.py demo and get past the infinite loop?
My script:
import paramiko
import forward
import MySQLdb
import cfg
import sys
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.WarningPolicy())
try:
client.connect(cfg.remhost, cfg.remport, username=cfg.user, password=cfg.password)
except Exception, e:
print '*** Failed to connect to %s:%d: %r' % (cfg.remhost, cfg.remport, e)
sys.exit(1)
try:
forward.forward_tunnel(3306, cfg.remhost, 3306, client.get_transport())
except KeyboardInterrupt:
print 'C-c: Port forwarding stopped.'
sys.exit(0)
try:
db = MySQLdb.connect('127.0.0.1', cfg.dbuser, cfg.dbpass, cfg.dbname)
except Exception, e:
print 'Failed to connect to database'
sys.exit(1)
try:
cursor = self.db.cursor(MySQLdb.cursors.DictCursor)
sql = 'SELECT * FROM ' + cfg.dbtable
cursor.execute(sql)
results = cursor.fetchall()
print str(len(results))
except Exception, e:
print 'Failed to query database'
sys.exit(1)
Here is the main chunk of the forward.py demo code:
class ForwardServer (SocketServer.ThreadingTCPServer):
daemon_threads = True
allow_reuse_address = True
class Handler (SocketServer.BaseRequestHandler):
def handle(self):
try:
chan = self.ssh_transport.open_channel('direct-tcpip',
(self.chain_host, self.chain_port),
self.request.getpeername())
except Exception, e:
verbose('Incoming request to %s:%d failed: %s' % (self.chain_host,
self.chain_port,
repr(e)))
return
if chan is None:
verbose('Incoming request to %s:%d was rejected by the SSH server.' %
(self.chain_host, self.chain_port))
return
verbose('Connected! Tunnel open %r -> %r -> %r' % (self.request.getpeername(),
chan.getpeername(), (self.chain_host, self.chain_port)))
while True:
r, w, x = select.select([self.request, chan], [], [])
if self.request in r:
data = self.request.recv(1024)
if len(data) == 0:
break
chan.send(data)
if chan in r:
data = chan.recv(1024)
if len(data) == 0:
break
self.request.send(data)
chan.close()
self.request.close()
verbose('Tunnel closed from %r' % (self.request.getpeername(),))
def forward_tunnel(local_port, remote_host, remote_port, transport):
# this is a little convoluted, but lets me configure things for the Handler
# object. (SocketServer doesn't give Handlers any way to access the outer
# server normally.)
class SubHander (Handler):
chain_host = remote_host
chain_port = remote_port
ssh_transport = transport
ForwardServer(('', local_port), SubHander).serve_forever()
def verbose(s):
if g_verbose:
print s
I think you need the handler forward code to run in its own thread and use queues to communicate to it.
Or pull out the relevant calls and stuff it is in your own loop. Hmmm, I am not sure how this works exactly.
Do you want your mysql calls to work with it in your program or forward from a different program?
I am the upstream author of a Pyhon module called Python X2Go that heavily uses Paramiko for SSH session management.
Please take a look at the forward.py file in the code:
http://code.x2go.org/gitweb?p=python-x2go.git;a=blob;f=x2go/forward.py
The code of Python X2Go heavily uses Python gevent for server-client communication, port forwarding etc.
Greets,
Mike
How can I make a simple server(simple as in accepting a connection and print to terminal whatever is received) accept connection from multiple ports or a port range?
Do I have to use multiple threads, one for each bind call. Or is there another solution?
The simple server can look something like this.
def server():
import sys, os, socket
port = 11116
host = ''
backlog = 5 # Number of clients on wait.
buf_size = 1024
try:
listening_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listening_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
listening_socket.bind((host, port))
listening_socket.listen(backlog)
except socket.error, (value, message):
if listening_socket:
listening_socket.close()
print 'Could not open socket: ' + message
sys.exit(1)
while True:
accepted_socket, adress = listening_socket.accept()
data = accepted_socket.recv(buf_size)
if data:
accepted_socket.send('Hello, and goodbye.')
accepted_socket.close()
server()
EDIT:
This is an example of how it can be done. Thanks everyone.
import socket, select
def server():
import sys, os, socket
port_wan = 11111
port_mob = 11112
port_sat = 11113
sock_lst = []
host = ''
backlog = 5 # Number of clients on wait.
buf_size = 1024
try:
for item in port_wan, port_mob, port_sat:
sock_lst.append(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
sock_lst[-1].setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
sock_lst[-1].bind((host, item))
sock_lst[-1].listen(backlog)
except socket.error, (value, message):
if sock_lst[-1]:
sock_lst[-1].close()
sock_lst = sock_lst[:-1]
print 'Could not open socket: ' + message
sys.exit(1)
while True:
read, write, error = select.select(sock_lst,[],[])
for r in read:
for item in sock_lst:
if r == item:
accepted_socket, adress = item.accept()
print 'We have a connection with ', adress
data = accepted_socket.recv(buf_size)
if data:
print data
accepted_socket.send('Hello, and goodbye.')
accepted_socket.close()
server()
I'm not a python guy, but the function you are interested in is "select". This will allow you to watch multiple sockets and breaks out when activity occurs on any one of them.
Here's a python example that uses select.
Since Python's got so much overhead, multithreaded apps are a big point of debate. Then there's the whole blocking-operation-GIL issue too. Luckily, the Python motto of "If it seems like a big issue, someone's probably already come up with a solution (or several!)" holds true here. My favorite solution tends to be the microthread model, specifically gevent.
Gevent is an event-driven single-thread concurrency library that handles most issues for you out of the box via monkey-patching. gevent.monkey.patch_socket() is a function that replaces the normal socket calls with non-blocking variants, polling and sleeping to allow the switch to other greenlets as need be. If you want more control, or it's not cutting it for you, you can easily manage the switching with select and gevent's cooperative yield.
Here's a simple example.
import gevent
import socket
import gevent.monkey; gevent.monkey.patch_socket()
ALL_PORTS=[i for i in xrange(1024, 2048)]
MY_ADDRESS = "127.0.0.1"
def init_server_sock(port):
try:
s=socket.socket()
s.setblocking(0)
s.bind((MY_ADDRESS, port))
s.listen(5)
return s
except Exception, e:
print "Exception creating socket at port %i: %s" % (port, str(e))
return False
def interact(port, sock):
while 1:
try:
csock, addr = sock.accept()
except:
continue
data = ""
while not data:
try:
data=csock.recv(1024)
print data
except:
gevent.sleep(0) #this is the cooperative yield
csock.send("Port %i got your message!" % port)
csock.close()
gevent.sleep(0)
def main():
socks = {p:init_server_sock(p) for p in ALL_PORTS}
greenlets = []
for k,v in socks.items():
if not v:
socks.pop(k)
else:
greenlets.append(gevent.spawn(interact, k, v))
#now we've got our sockets, let's start accepting
gevent.joinall(greenlets)
That would be a super-simple, completely untested server serving plain text We got your message! on ports 1024-2048. Involving select is a little harder; you'd have to have a manager greenlet which calls select and then starts up the active ones; but that's not massively hard to implement.
Hope this helps! The nice part of the greenlet-based philosophy is that the select call is actually part of their hub module, as I recall, which will allow you to create a much more scalable and complex server more easily. It's pretty efficient too; there are a couple benchmarks floating around.
If you really wanted to be lazy (from a programmer standpoint, not an evaluation standpoint), you could set a timeout on your blocking read and just loop through all your sockets; if a timeout occurs, there wasn't any data available. Functionally, this is similar to what the select is doing, but it is taking that control away from the OS and putting it in your application.
Of course, this implies that as your sleep time gets smaller, your program will approach 100% CPU usage, so you wouldn't use it on a production app. It's fine for a toy though.
It would go something like this: (not tested)
def server():
import sys, os, socket
port = 11116
host = ''
backlog = 5 # Number of clients on wait.
buf_size = 1024
NUM_SOCKETS = 10
START_PORT = 2000
try:
socket.setdefaulttimeout(0.5) # raise a socket.timeout error after a half second
listening_sockets = []
for i in range(NUM_SOCKETS):
listening_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listening_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
listening_socket.bind((host, START_PORT + i))
listening_socket.listen(backlog)
listening_sockets.append(listening_socket)
except socket.error, (value, message):
if listening_socket:
listening_socket.close()
print 'Could not open socket: ' + message
sys.exit(1)
while True:
for sock in listening_sockets:
try:
accepted_socket, adress = sock_socket.accept()
data = sock.recv(buf_size)
if data:
sock_socket.send('Hello, and goodbye.')
sock.close()
except socket.timeout:
pass
server()