I use unittests to check correctness of TCP client communication, so I need some TCP server that I can control it and that it sends to client (and when).
A simple test should look like:
server = Server("localhost", 5555)
server.start()
client.connect()
self.assertTrue("login_message" in server.received_data)
server.send_to_client(reject_messages)
self.assertTrue("login_again" in server.received_data)
time.sleep(10)
self.assertTrue("login_again_and_again" in server.newest_received_data)
server.stop()
self.assertTrue("login failed" in client.logs)
I need the full flow control, what could be used for implementing Server?
Now I try to use threaded SocketServer, but I don't have an access neither to data, nor to controlling it..
I don't know if anybody needs this, but anyway:
I used gevent server
from gevent import sleep, socket
from gevent.server import StreamServer
class Connection:
def __init__(self, host, port):
self.server = StreamServer((host, port), self.handle)
self.data = []
self.socks = []
self.pointer = 0
def handle(self, sock, address):
self.socks.append(sock)
while True:
line = sock.recv(1024)
if line:
self.data += [line]
else:
break
sock.close()
self.socks.remove(sock)
def send(self, msg):
if self.socks:
sock2send = self.socks[-1]
try:
sock2send.send(msg)
except IOError, e:
print "Can't send message '%s'! Exception:" % msg, e
else:
print "No sockets to send the message to"
def start(self):
self.server.start()
def serve_forever(self):
self.server.serve_forever()
def close(self):
self.server.stop()
for sock in self.socks:
sock.close()
def new_data(self):
newest = self.data[self.pointer:]
self.pointer = len(self.data)
return newest
And then unittest looks like this:
def testTCPClient(self):
j = lambda x: "".join(x)
server = Connection("", 5555)
server.start()
client.run()
sleep(3)
data = j(server.new_data())
self.assertTrue("login" in data)
sleep(2)
server.send("login approve")
sleep(2)
data = j(server.new_data())
self.assertTrue("after_login" in data)
server.send("logout")
sleep(2)
data = j(server.new_data())
self.assertTrue("received_logout" in data)
server.close()
self.assertTrue("disconnected" in client.logs)
Related
This is a simple port forwarding proxy which listens on localhost and then forwards all the connection to a real proxy and sends back the received data to the user.
The server which accepts connections and listens:
class Server:
def __init__(self):
self.server = eventlet.listen(('127.0.0.1', 8080))
self.chunk_size = 8192
def forward_connection(self, fd):
print('in fwd_conn')
data = b''
while True:
print('reading data')
x = fd.readline()
if not x.strip():
break
data += x
print('Got request:', data)
client = Client('45.55.31.207', 8081, data) # Connecting to proxy
buff = client.read_from_proxy()
fd.write(buff)
fd.flush()
def serve_client(self):
pool = eventlet.GreenPool()
while True:
try:
new_sock, addr = self.server.accept()
print('accepted:', addr)
pool.spawn(self.forward_connection, new_sock.makefile('rbw'))
except (SystemExit, KeyboardInterrupt):
break
server = Server()
server.serve_client()
This part of the code connects to the 'real' proxy, receives the data and sends it back. But as commented in the read_from_proxy function, it isn't receiving any data:
class Client:
''' All connections from Server are forwarded to Client which then
forwards it to the proxy '''
def __init__(self, ip, port, request):
self.sock = socket.socket()
self.sock.connect((ip, port))
print('in client')
print('sent request:', request)
self.request = request
def read_from_proxy(self):
self.sock.sendall(self.request)
data = b''
while True:
print('reading data from proxy') # this executes
x = self.sock.recv(8192) # but this doesn't, it gets blocked here
print('got x:', x)
if not x.strip():
break
data += x
print('read all data')
return data
Where am I going wrong?
Hi i'm trying to send multiple messages to the tcp server but in my client i got an error that data is referenced before assignment. If i send one message there will be no error but if i try to send more than one it returns the error.
tcp server:
class Connect(object):
def __init__(self):
try:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print('socket cannot be created')
server_address = ('169.254.34.240', 10000)
#print('starting up: ' + server_address)
self.sock.bind(server_address)
self.sock.listen(1)
def listen(self):
while True:
connection, client_address = self.sock.accept()
print('client connected')
try:
data = connection.recv(16)
print(data)
if data == "STATUS":
connection.sendall("vision=ready")
elif data == "MEASURE":
connection.sendall("vision=computing")
elif data == "GET_RESULT":
connection.sendall("x=1.5,y=0.25,z=0.14,a=0.15")
else:
connection.sendall("wrong command")
finally:
connection.close()
def main():
connect = Connect()
connect.listen()
if __name__=='__main__':
main()
my tcp client which is sending messages:
class Connect(object):
def __init__(self):
# Create a TCP/IP socket
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect the socket to the port on the server given by the caller
print('connecting to host')
self.sock.connect(('169.254.34.240',10000))
def send(self, command):
try:
message = command
print('sending: ' + message)
self.sock.sendall(message)
amount_received = 0
amount_expected = len(message)
while amount_received < amount_expected:
data = self.sock.recv(16)
amount_received += len(data)
print('received: ' + data)
finally:
self.sock.close()
return data
def main():
connect = Connect()
print connect.send("STATUS")
print connect.send("MEASURE")
if __name__=='__main__':
main()
so anyone an idea, i suppose i don't end correctly or something, i thought it had something to do about my while in the client?
The problem is that you are calling self.sock.close() after each request without creating a new socket. You will need to create a new socket after each time you close it.
You can solve this by creating a connection per request as follows:
class Connect(object):
def connect(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('connecting to host')
sock.connect(('127.0.0.1',10000))
return sock
def send(self, command):
sock = self.connect()
recv_data = ""
data = True
print('sending: ' + command)
sock.sendall(command)
while data:
data = sock.recv(1024)
recv_data += data
print('received: ' + data)
sock.close()
return recv_data
def main():
connect = Connect()
print connect.send("STATUS")
print connect.send("MEASURE")
Providing full stack trace would help, pointing to exact line, where is the problem present. Learn reading these stack traces, they look boring, but provide valuable information like source file and line where it comes from.
Reading your code I suspect, that it fails at finally block, where you return data.
data will not have assigned value in case, the while amount_received < amount_expected would not allow even the first round in the loop or if withing that loop would happen an exception on the line self.sock.recv(16).
Btw.: you are assuming, that length of response will be the same as length of request, but your server does not provide responses with such length.
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
iv created a simple async client and server but im unable to get the client to reply after receiving the first time. It seems the server can send back a reply after receiving from the client but the client cant:
here is the client's session:
[mike#mike Public]$ python cl.py
buf got your stuff
dded callback ## this is a log addded to see if execution got where i wanted
and here is the server's log:
[mike#mike Public]$ python that.py
buf ehlo localhost
i was expecting some sort of ping pong effect where one send then the other then rinse lather repeat.
here is the client's code:
import socket
import fcntl, os, io, time, functools
from tornado import ioloop
class Punk(object):
def __init__(self):
self.loop = ioloop.IOLoop.instance()
self.address = 'blah.sock'
self.authkey = "none"
self.sock = socket.socket(socket.AF_UNIX)
def setup(self):
self.sock.connect(self.address)
fcntl.fcntl(self.sock, fcntl.F_SETFL, os.O_NONBLOCK)
self.sock.sendall("ehlo localhost")
self.fd = self.sock.fileno()
self.loop.add_handler(self.fd,self.reader,self.loop.READ)
self.loop.start()
def reader(self,fd,event):
result = b""
if event == self.loop.READ:
try:
while True:
servrep = self.sock.recv(1024)
if not servrep:
break
result += servrep
self.prnt(result)
break
except Exception as e:
print "this %s happend"%e
return
def prnt(self,buf):
print "buf %s"%buf
tim = time.time() + 2
self.loop.instance().add_timeout(tim, self.reply)
#callbac = functools.partial(self.loop.add_timeout,tim,self.reply)
#self.loop.add_callback(self.reply) ### i tried this too
print "added callback"
def reply(self):
self.sock.sendall(" clent got your stuff")
if __name__ == "__main__":
bob = Punk()
bob.setup()
and here is the server:
import socket
import fcntl, os, io, time, functools
from array import array
from tornado import ioloop
class Player(object):
def __init__(self):
self.loop = ioloop.IOLoop.instance()
self.address = 'blah.sock'
self.authkey = "none"
self.sock = socket.socket(socket.AF_UNIX)
def setup(self):
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
self.sock.bind(self.address)
fcntl.fcntl(self.sock, fcntl.F_SETFL, os.O_NONBLOCK)
self.sock.listen(1)
self.fd = self.sock.fileno()
self.loop.add_handler(self.fd,self.reader,self.loop.READ)
self.loop.start()
def reader(self,fd,event):
result = b""
if event == self.loop.READ:
self.conn, self.addr = self.sock.accept()
try:
while True:
maxrep = self.conn.recv(1024)
if not maxrep:
break
result += maxrep
self.prnt(result)
break
except Exception as e:
print "this %s happend"%e
return
def prnt(self,buf):
print "buf %s"%buf
tim = time.time() + 2
self.loop.instance().add_timeout(tim, self.reply)
#callbac = functools.partial(self.loop.add_timeout,tim,self.reply)
#self.loop.add_callback(callbac)
def reply(self):
self.conn.sendall("got your stuff")
if __name__ == "__main__":
bob = Player()
bob.setup()
i had set my sockets to nonblock mode, but i did not catch an error when accepting from
a nonblock state when there is no connection:
here:
def reader(self,fd,event):
result = b""
if event == self.loop.READ:
self.conn, self.addr = self.sock.accept()
should be
def reader(self,fd,event):
result = b""
if event == self.loop.READ:
try:
self.conn, self.addr = self.sock.accept() # we get stuck here
self.connl.append(self.conn)
except Exception as e:
pass
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.