I'm making a proxy for my project and I'm trying to send to the browser (Firefox) an HTTP header to continue the "Conversation" between me(Proxy server) and the browser. The issue is: when I'm refreshing any page, the page Keeping loading. I use socket and select for the proxy:
import socket, select
#Sending a message for the waiting list
def send_Waiting_Messages(wlist):
for msg in messages_to_send:
clientSocket, data = msg
if clientSocket in wlist:
clientSocket.send('HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n')
messages_to_send.remove(msg)
serverSocket = socket.socket()
serverSocket.bind(('0.0.0.0',8080))
serverSocket.listen(10)
open_client_sockets = []
messages_to_send = []
while True:
rlist, wlist, xlist = select.select([serverSocket] + open_client_sockets, open_client_sockets, [])
for currentSocket in rlist:
if currentSocket is serverSocket:
newSocket, addr = serverSocket.accept()
open_client_sockets.append(newSocket)
else:
data = currentSocket.recv(1024)
if data == "":
open_client_sockets.remove(currentSocket)
print 'Conn is closed'
else:
print data
messages_to_send.append((currentSocket, 'Hello, ' + data))
send_Waiting_Messages(wlist)
These lines:
clientSocket.send('HTTP/1.1 200 OK\r\n')
clientSocket.send('Content-Type: text/html\r\n\r\n')
are for sending the header.
Thanks for helpers!!
notice that every the send_Waiting_Messages function is sending the same response to all of your connected clients. I reccomend to replace it with the basic send function when the socket is in the wlist.
This will probably work
import socket, select
serverSocket = socket.socket()
serverSocket.bind(('0.0.0.0',8080))
serverSocket.listen(10)
open_client_sockets = []
while True:
rlist, wlist, xlist = select.select([serverSocket] + open_client_sockets, open_client_sockets, [])
for currentSocket in rlist:
if currentSocket is serverSocket:
newSocket, addr = serverSocket.accept()
open_client_sockets.append(newSocket)
else:
data = currentSocket.recv(2048)
if data == "":
open_client_sockets.remove(currentSocket)
print 'Conn is closed'
else:
print data
content_to_send = "The content that you want to send"
currentSocket.send("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length:"+str(len(content_to_send))+"\r\n\r\n"+content_to_send)
Related
I'm sorry if this is a really dumb question, I'm sure someone could probably find the answer in a minute, I've just recently been getting into Python sockets.
I want my server to continually send a stream of data to my client, but for some reason, after receiving the first piece of data my client just does not receive/print out any more data.
My simplified server.py:
while True:
#do some stuff with dfwebsites here
senddata = True
#time.sleep(1)
#Starting the sending data part
HEADERSIZE = 10
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(),1236))
s.listen(5) #queue of five
while senddata==True:
clientsocket, address = s.accept()
print(f"Connection from {address} has been established!")
d = pd.DataFrame(dfwebsites)
msg = pickle.dumps(d)
#header to specify length
#msg = "Welcome to the server!"
msg = bytes(f'{len(msg):<{HEADERSIZE}}','utf-8')+msg
clientsocket.send(msg) #type of bytes is utf-8
#clientsocket.close()
senddata = False
My client.py:
import socket
import pickle
import time
HEADERSIZE = 10
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 1236))
while True:
full_msg = b''
new_msg = True
while True:
msg = s.recv(1024)
if new_msg:
print("new msg len:",msg[:HEADERSIZE])
msglen = int(msg[:HEADERSIZE])
new_msg = False
print(f"full message length: {msglen}")
full_msg += msg
print(len(full_msg))
if len(full_msg)-HEADERSIZE == msglen:
print("full msg recvd")
print(full_msg[HEADERSIZE:])
print(pickle.loads(full_msg[HEADERSIZE:]))
new_msg = True
full_msg = b""
Why can it not receive more than one peice of data?
Thank you so much for your help! I would really love even a comment telling me how to improve my qeustion!
To send more than one message to each client, you need a loop after the accept() has happened.
#!/usr/bin/env python
import socket
import pickle
import pandas as pd
HEADERSIZE = 10
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(),1236))
s.listen(5) # only one client at a time, but let up to five wait in line
while True:
clientsocket, address = s.accept()
print(f"Connection from {address} has been established!")
while senddata:
# FIXME: refresh dfwebsites every time through this loop?
d = pd.DataFrame(dfwebsites)
msg = pickle.dumps(d)
msg = bytes(f'{len(msg):<{HEADERSIZE}}','utf-8')+msg
try:
clientsocket.send(msg) #type of bytes is utf-8
except socket.error as exc:
print(f"Ending connection from client {address} due to {exc}")
# FIXME: Do the below only when you want to disconnect a client
#senddata = False
clientsocket.close()
I build a server proxy with Python by using socket and select libraries. I got an issue: When the proxy is ready to use and I reload a website it doenst reload it. I get only 3 headers from the server and the client send to the server the variable "data" that contains the client header. If you run the program you'll be able to understand better.
** HostFliter is a function that gets the first line of the header, and returns the domain of the website.
import socket, select
def HostFliter(dataSplit):
dataSplit = dataSplit[0]
print dataSplit," datasplit"
if dataSplit.split(" ")[0] == "GET" or dataSplit.split(" ")[0] == "POST":
dataSplit = dataSplit.split(" ")[1]
dataSplit = dataSplit.replace("http://","")
if dataSplit.find('/') != -1:
dataSplit = dataSplit.split('/')[0]
return dataSplit
else:
return ""
clientSocket = socket.socket()
clientSocket.bind(('0.0.0.0', 80))
clientSocket.listen(100)
open_client_sockets = []
while True:
rlist, wlist, xlist = select.select([clientSocket] + open_client_sockets, open_client_sockets, [])
for currentSocket in rlist:
if currentSocket is clientSocket:
newSocket, addr = clientSocket.accept()
open_client_sockets.append(newSocket)
else:
data = currentSocket.recv(4096)
print data
if data == "":
currentSocket.send("")
currentSocket.close()
open_client_sockets.remove(currentSocket)
print 'Conn is closed'
else:
dataSplit = data.split("\r\n")
Host = HostFliter(dataSplit)
print Host, " Host"
if Host == "":
break
serverSocket = socket.socket()
serverSocket.connect((Host, 80))
serverSocket.send(data)
print "Sent to server"
response = serverSocket.recv(4096)
new_res = ""
while len(new_res) > 0:
new_res = ""
new_res = serverSocket.recv(4096)
response += new_res
currentSocket.send(response)
print "Sent " + Host
Thanks for the helpers!!
How can I have a Python socket server tell me when there is a connection and then CONTINUE to give me back data that the client sends? When I do it, it connects and then just loops over, telling me it connected over and over again.
I,just want it to connect and then continually check (or grab) data sent to the server.
Also, how can I tell if the client disconnected?
address = ('', 7777)
server_socket = socket(AF_INET, SOCK_STREAM)
server_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
try:
server_socket.bind(address)
except Exception, e:
print colored("Address already in use", 'red')
server_socket.listen(2)
print colored("Socket ready", 'blue')
while True:
client_socket, addr = server_socket.accept()
hostIP = addr[0]
port = addr[1]
try:
host = gethostbyaddr(hostIP)[0]
except:
host = hostIP
print colored("Got connection from: " + host, 'blue')
try:
recv_data = server_socket.recv(2048)
print("Got: " + recv_data)
except:
print "nothing"
recv_data = "" # this is because I test what it is later, but that's irrevlevant.
Thanks
You didn't do anything with client_socket; ie: the actual client connection. Furthermore, the server
cannot know how much the client wants to send and so it must CONTINUE (ie: in a
loop) to receive data. When the connection sends 'empty' data, the connection
is terminated and the server goes back to listening. If you want the server to
accept new connections and continue to receive data from existing connections
look up the threading module.
import socket
address = ('', 7777)
server_socket = socket.socket(AF_INET, SOCK_STREAM)
server_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
try:
server_socket.bind(address)
except Exception, e:
print colored("Address already in use", 'red')
server_socket.listen(2)
print colored("Socket ready", 'blue')
while True:
client_socket, addr = server_socket.accept()
hostIP = addr[0]
port = addr[1]
try:
host = gethostbyaddr(hostIP)[0]
except:
host = hostIP
print colored("Got connection from: " + host, 'blue')
while True:
try:
recv_data = client_socket.recv(2048)
if not recv_data:
break
print("Got: " + recv_data)
except socket.error, e:
print "nothing"
recv_data = "" # this is because I test what it is later, but that's irrevlevant.
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.
This is a simple server. When you open the browser type into the address of the server, and it will response a status code and the content of the requested html.
#import socket module
from socket import *
serverSocket = socket(AF_INET, SOCK_STREAM)
#Prepare a sever socket
serverSocket.bind((socket.gethostname(), 4501))#Fill in start
serverSocket.listen(5)#Fill in end
while True:
#Establish the connection
print 'Ready to serve...'
connectionSocket, addr = serverSocket.accept()#Accepts a TCP client connection, waiting until connection arrives
print 'Required connection', addr
try:
message = connectionSocket.recv(32)#Fill in start #Fill in end
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()#Fill in start #Fill in end
#Send one HTTP header line into socket
connectionSocket.send('HTTP/1.0 200 OK\r\n\r\n')#Fill in start
#Send the content of the requested file to the client
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i])
connectionSocket.close()
except IOError:
#Send response message for file not found
connectionSocket.send('404 Not Found')#Fill in start
#Fill in end
#Close client socket
connectionSocket.close()#Fill in start
serverSocket.close()#Fill in end
There are many ways to do this. Here's a way to use a pool of worker threads:
import Queue
import threading
num_workers = 10
work_q = Queue.Queue()
def worker(work_q):
while True:
connection_socket = work_q.get()
if connection_socket is None:
break
try:
message = connectionSocket.recv()
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()
connectionSocket.send('HTTP/1.0 200 OK\r\n\r\n')
connectionSocket.send(outputdata)
except IOError:
connectionSocket.send('404 Not Found')
finally:
connectionSocket.close()
workers = []
for i in range(num_workers):
t = threading.Thread(target=worker, args=(work_q,))
t.start()
workers.append(t)
while True:
#Establish the connection
print 'Ready to serve...'
connectionSocket, addr = serverSocket.accept()
print 'Required connection', addr
work_q.put(connectionSocket)