if i running this code in console, it running an got response from the server, but it doesn't running and get null response while trying write that code in Odoo addons
xml_data = xml_formatter()
if xml_data != 'pas':
content_length = len(xml_data)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
request = '''
POST /{service} HTTP/1.1
Content-Type: text/xml
Content-Length: {content_length}
{xml}'''.format(service=service, xml=xml_data, content_length=content_length)
if bytes != str: # Testing if is python2 or python3
request = bytes(request, 'utf-8')
buffer = b""
try:
client.connect((target_host, target_port))
try:
client.send(request)
while True:
chunk = client.recv(2048)
if len(chunk) == 0:
break
buffer = buffer + chunk
except socket.error as msg:
_logger.error("Caught exception socket.error : %s" %msg )
finally:
client.close()
except socket.error as msg:
_logger.error("Caught exception socket.error : %s" %msg )
else:
print('NAH!')
Related
So I have this server file which is ok, always is up for connections, after sending a message from the client, client connection closes. I want the client to be up again for sending a message (get input again). I don't want to start the client again (in my case it's odev1.py)
# server.py
import socket
HOST = socket.gethostname()
PORT = 65432
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
server_socket.bind((HOST, PORT))
server_socket.listen()
while True:
print('waiting for a connection')
connection, client_address = server_socket.accept()
try:
print(f'{client_address[0]} has entered the chat\n')
while True:
data = connection.recv(1024)
print(f'{client_address[0]} - {str(data, encoding="utf-8")}')
if data:
print('sending data back to the client')
connection.sendall(data)
else:
print('no data from', client_address[0])
break
finally:
print("Closing current connection")
connection.close()
this is my client ->
# client.py
import sys
import socket
host = socket.gethostname()
port = 65432
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error as e:
print("Error creating socket: %s" % e)
sys.exit(1)
# Second try-except block -- connect to given host/port
try:
s.connect((host, port))
except socket.gaierror as e:
print("Address-related error connecting to server: %s" % e)
sys.exit(1)
except socket.error as e:
print("Connection error: %s" % e)
sys.exit(1)
# Third try-except block -- sending data
try:
# NOTE: I want it to take input again
# Send data
message = input('write something: ')
s.sendall(message.encode('utf-8'))
print('sending {!r}'.format(message))
# Look for the response
amount_received = 0
amount_expected = len(message)
while amount_received < amount_expected:
data = s.recv(1024)
amount_received += len(data)
print('received {!r}'.format(data))
finally:
print('closing socket')
s.close()
this is how it looks right now:
So I'm trying to create a web proxy to intercept the browser traffic, however working with http was easy and I was able to do easily but when it comes to https I get this not informative error and I don't know what is wrong, all I can find is that the exception is triggered when this line is executed (client_socket, address) = ssl_socket.accept()
import socket
import thread
import ssl
def proxy_server():
server_scoket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# http_listener(server_scoket)
https_listener(server_scoket)
# server_scoket.close()
def https_listener(server_scoket):
ssl_socket = ssl.wrap_socket(server_scoket,keyfile='localhost.key',certfile='localhost.crt',server_side=1)
ssl_socket.bind(('127.0.0.1',9000))
ssl_socket.listen(50)
while True:
try :
(client_socket, address) = ssl_socket.accept()
thread.start_new_thread(proxy_thread, (client_socket, address))
except Exception as e:
print "Error {}".format(e)
to test the code I tried to browse to the python website : www.python.org and here is the output :
Error [SSL: HTTPS_PROXY_REQUEST] https proxy request (_ssl.c:727)
UPDATE 1 :
the full code :
import socket
import thread
import ssl
def proxy_server():
server_scoket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
http_listener(server_scoket)
# https_listener(server_scoket)
# server_scoket.close()
def https_listener(server_scoket):
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.load_cert_chain('localhost.crt', 'localhost.key')
server_scoket.bind(('127.0.0.1',9000))
server_scoket.listen(5)
ssl_socket = context.wrap_socket(server_scoket,server_side=True)
while True:
try :
(client_socket, address) = ssl_socket.accept()
thread.start_new_thread(proxy_thread, (client_socket, address))
except Exception as e:
print "Error {}".format(e)
def http_listener(server_scoket):
try :
server_scoket.bind(('127.0.0.1',9000))
server_scoket.listen(50)
while True:
(client_socket, address) = server_scoket.accept()
thread.start_new_thread(proxy_thread, (client_socket, address))
except KeyboardInterrupt :
print "\n shutting down"
except Exception as e :
print "Error : {}".format(e)
def proxy_thread(connection, client_address):
request = connection.recv(5000)
url = request.split('\n')[0].split(' ')[1]
splited_request = request.split('\r\n\r\n')
headers = splited_request[0].split('\n')
body = splited_request[1]
port = 0
print "---------"
print request
print "---------"
splitted_url = url.split(':')
url = splitted_url[1][2:]
base_url = url.split('/')[0]
path_url = url[len(base_url):]
if (len(splitted_url) < 3):
port = 80
else:
port = splitted_url[2]
try :
splited_line = headers[0].split(' ')
if (splited_line[0] != "CONNECT"):
headers[0] = "{} {} {}".format(splited_line[0],path_url,splited_line[2])
else:
base_url = headers[0].split(' ')[1]
new_headers = ""
for index,header in enumerate(headers) :
if (index != len(headers) - 1):
headers[index] = "{}\n".format(header)
new_headers = "".join(headers)
request = "{} \r\n\r\n {}".format(new_headers,body)
if (splitted_url[0] == "https"):
https_proxy(base_url,443,request,connection)
else:
http_proxy(base_url,443,request,connection)
connection.close()
except OSError, message:
if s:
s.close()
if connection:
connection.clos()
print "Error messgae : "+ message
except Exception as e:
print "Error : {}".format(e)
def http_proxy(base_url,port,request,connection):
print "------ http request start -----"
print request
print "------ request ends -----"
print port
if(request.split(' ')[0] == 'CONNECT'):
reply = "HTTP/1.1 200 OK\r\n\r\n"
connection.sendall(reply)
print request.split(' ')[0]
print "replied HTTP/1.1 200 OK\r\n\r\n"
return
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((base_url,port))
s.sendall(request)
while True:
data = s.recv(50000)
if (len(data) > 0):
connection.sendall(data)
else:
break
s.close()
def https_proxy(base_url,port,request,connection):
print "------ https request start -----"
print request
print "------ request ends -----"
print port
sp_base_url = base_url.split(':')
base_url = sp_base_url[0] if len(sp_base_url) > 1 else base_url
context = ssl.create_default_context()
sock = socket.create_connection(("cdn.sstatic.net",443))
print port
context.load_verify_locations('/etc/ssl/certs/ca-certificates.crt')
ssock = context.wrap_socket(sock, server_hostname="cdn.sstatic.net")
print ssock.version()
ssock.sendall(request)
while True:
data = ssock.recv(5000)
if (len(data) > 0):
print data
connection.sendall(data)
else:
break
sock.close()
connection.close()
print "You can use the following proxy : \n host : 127.0.0.1 \n port : 9000 \n"
proxy_server()
the execution output :
You can use the following proxy :
host : 127.0.0.1
port : 9000
---------
CONNECT www.pythonconverter.com:443 HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Proxy-Connection: keep-alive
Connection: keep-alive
Host: www.pythonconverter.com:443
---------
------ http request start -----
CONNECT www.pythonconverter.com:443 HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Proxy-Connection: keep-alive
Connection: keep-alive
Host: www.pythonconverter.com:443
------ request ends -----
443
CONNECT
replied HTTP/1.1 200 OK
but then from my understanding I should get a new connection or at least a request on the same socket from the browser, however that does not happen !
I'm trying to send a large file (.avi) over socket by sending the content of the file in chunks (a little bit like torrents). The problem is that the script doesn't send the file. I'm out of ideas here.
Any help or twerking of the script would be very appreciated.
Server:
import socket
HOST = ""
PORT = 8050
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((HOST, PORT))
sock.listen(1)
conn, addr = sock.accept()
print("Connected by ", str(addr))
while 1:
data = conn.recv(1024)
if data.decode("utf-8") == 'GET':
with open(downFile,'rb') as output:
l = output.read(1024)
while (l):
conn.send(l)
l = output.read(1024)
output.close()
conn.close()
Client:
import socket
HOST = "localhost"
PORT = 8050
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST,PORT))
while 1:
message = input()
sock.send(bytes(message,'UTF-8'))
conn.send(str.encode('GET'))
with open(downFile, 'wb+') as output:
while True:
rec = str(sock.recv(1024), "utf-8")
if not rec:
break
output.write(rec)
output.close()
print('Success!')
sock.close()
Here are a working client and server that should demonstrate transferring a file over a socket. I made some assumptions about what your code was supposed to do, for example, I assumed that the initial message the client sent to the server was supposed to be the name of the file to download.
The code also includes some additional functionality for the server to return an error message to the client. Before running the code, make sure the directory specified by DOWNLOAD_DIR exists.
Client:
import socket
import sys
import os
HOST = "localhost"
PORT = 8050
BUF_SIZE = 4096
DOWNLOAD_DIR = "downloads"
def download_file(s, down_file):
s.send(str.encode("GET\n" + down_file))
rec = s.recv(BUF_SIZE)
if not rec:
return "server closed connection"
if rec[:2].decode("utf-8") != 'OK':
return "server error: " + rec.decode("utf-8")
rec = rec[:2]
if DOWNLOAD_DIR:
down_file = os.path.join(DOWNLOAD_DIR, down_file)
with open(down_file, 'wb') as output:
if rec:
output.write(rec)
while True:
rec = s.recv(BUF_SIZE)
if not rec:
break
output.write(rec)
print('Success!')
return None
if DOWNLOAD_DIR and not os.path.isdir(DOWNLOAD_DIR):
print('no such directory "%s"' % (DOWNLOAD_DIR,), file=sys.stderr)
sys.exit(1)
while 1:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
except Exception as e:
print("cannot connect to server:", e, file=sys.stderr)
break
file_name = input("\nFile to get: ")
if not file_name:
sock.close()
break
err = download_file(sock, file_name)
if err:
print(err, file=sys.stderr)
sock.close()
Server:
import socket
import sys
import os
HOST = ""
PORT = 8050
BUF_SIZE = 4096
def recv_dl_file(conn):
data = conn.recv(1024)
if not data:
print("Client finished")
return None, None
# Get command and filename
try:
cmd, down_file = data.decode("utf-8").split("\n")
except:
return None, "cannot parse client request"
if cmd != 'GET':
return None, "unknown command: " + cmd
print(cmd, down_file)
if not os.path.isfile(down_file):
return None, 'no such file "%s"'%(down_file,)
return down_file, None
def send_file(conn):
down_file, err = recv_dl_file(conn)
if err:
print(err, file=sys.stderr)
conn.send(bytes(err, 'utf-8'))
return True
if not down_file:
return False # client all done
# Tell client it is OK to receive file
sent = conn.send(bytes('OK', 'utf-8'))
total_sent = 0
with open(down_file,'rb') as output:
while True:
data = output.read(BUF_SIZE)
if not data:
break
conn.sendall(data)
total_sent += len(data)
print("finished sending", total_sent, "bytes")
return True
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((HOST, PORT))
sock.listen(1)
keep_going = 1
while keep_going:
conn, addr = sock.accept()
print("Connected by", str(addr))
keep_going = send_file(conn)
conn.close() # close clien connection
print()
sock.close() # close listener
I'm new to sockets. I've written a simple 'proxy' server in Python that will just catch the data from the remote server and send it to my client (browser). I was wondering: is there a way to send the response_text without a time.sleep? While i try to delete time.sleep(0.5) I only get one package of data from the remote server so the 'Content-lenght' isn't equal to the length of the package and I get an error (I'm using recv() to get a buffer with size equaled to buffer_size, so if the server data needs more then one package of 4096 bytes I need to catch it in the next package). With the time.sleep i get all the packages of data from the remote server and I can send the data to my browser. Am I doing something wrong? Or I just don't know enough? Can someone help?
The code:
# coding: utf-8
import socket
import sys
import time
from thread import *
max_conn = 5
buffer_size = 4096
def proxy_server(webserver, port, conn, addr, data):
try:
remote_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_sock.connect((webserver, port))
remote_sock.send(data)
response_text = ''
while True:
time.sleep(0.5)
response = remote_sock.recv(buffer_size)
response_text += response
if len(response) < buffer_size:
remote_sock.close()
break
conn.sendall(response_text)
conn.close()
except socket.error, msg:
print 'Proccessing error. Error Code: ' + str(msg[0]) + ', Wiadomość: ' + msg[1]
remote_sock.close()
conn.close()
sys.exit()
def conn_string(conn, data, address):
header = data.split('\r\n')
method, address, protocol = header[0].split(' ')
host_key, host_value = header[1].split(': ')
proxy_server(host_value, 80, conn, address, data)
def start():
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', 8001))
sock.listen(max_conn)
print 'Proxy: on'
except socket.error, msg:
print 'Failed creating a socket. Error Code: ' + str(msg[0]) + ', Wiadomość: ' + msg[1]
sys.exit()
while True:
try:
connection, address = sock.accept()
data = connection.recv(buffer_size)
# start_new_thread(conn_string, (connection, data, address))
conn_string(connection, data, address)
except KeyboardInterrupt:
sock.close()
print "Socket closed"
sys.exit()
if __name__ == "__main__":
start()
Don't use time.sleep() , it makes your proxy very slow , and its not efficient .
You need to set your socket in non-blocking mode , with a timeout .
You can do this with socket.settimeout()
I made a few modifications to your proxy_server , it should be much faster now .
def proxy_server(webserver, port, conn, addr, data):
try:
remote_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_sock.connect((webserver, port))
remote_sock.send(data)
remote_sock.settimeout(0.5)
response_text = ''
while True:
try :
response = remote_sock.recv(buffer_size)
if len(response) == 0:
break
except :
break
response_text += response
conn.sendall(response_text)
except socket.error, msg:
if str(msg) != 'timed out' :
print 'Proccessing error. Error Code: ' + str(msg[0]) + ', Wiadomość: ' + msg[1]
remote_sock.close()
conn.close()
The rest of your code is quite ok , but you may want to use multithreading
if you want to handle multiple clients at the same time .
I am trying to connect a html5 websocket to python. I have two files:
1. index.html
<script>
window.onload = function() {
var connection = new WebSocket("ws://localhost:9876/");
connection.onopen = function () {
connection.send('Ping');
};
connection.onerror = function (error) {
console.log('WebSocket Error ' + error);
};
connection.onmessage = function (e) {
console.log('Server: ' + e.data);
};
};
</script>
2. server.py
import socket
HOST = ''
PORT = 9876
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)
conn, addr = s.accept()
print 'Connected by', addr
conn.send("Hello")
while 1:
data = conn.recv(4096)
print data
if not data: break
conn.sendall(data)
conn.close()
After starting server.py, it keeps running until I open index.html in my browser. When I do so, I get on the console the following:
WebSocket connection to 'ws://localhost:9876/' failed:
WebSocket Error [object Event]
However, on the other side(server.py) I get:
Connected by('127.0.0.1', 55460)GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: localhost:9876
Origin: null
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: WP0GtT0hrdX1bKa0DepOHQ==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
Q What's wrong with my codes? How should I modify it so as to have biorder communication between them?
I am looking for something like this:
if data == 'kill': conn.close()
important edit
If I change in the index.html WebSocket("ws://localhost:9876/") to WebSocket("ws://html5rocks.websocket.org/echo") than it works. I guess that means that to problem is on the server.py side
clue #2
If I write WebSocket("ws://localhost/:9876") in the html, the python code cannot proceed the line conn, addr = s.accept()
You haven't response headers.
try ,
server.py
import socket, hashlib, base64, threading
class PyWSock:
MAGIC = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
HSHAKE_RESP = "HTTP/1.1 101 Switching Protocols\r\n" + \
"Upgrade: websocket\r\n" + \
"Connection: Upgrade\r\n" + \
"Sec-WebSocket-Accept: %s\r\n" + \
"\r\n"
LOCK = threading.Lock()
clients = []
def recv_data (self, client):
# as a simple server, we expect to receive:
# - all data at one go and one frame
# - one frame at a time
# - text protocol
# - no ping pong messages
data = bytearray(client.recv(512))
if(len(data) < 6):
raise Exception("Error reading data")
# FIN bit must be set to indicate end of frame
assert(0x1 == (0xFF & data[0]) >> 7)
# data must be a text frame
# 0x8 (close connection) is handled with assertion failure
assert(0x1 == (0xF & data[0]))
# assert that data is masked
assert(0x1 == (0xFF & data[1]) >> 7)
datalen = (0x7F & data[1])
#print("received data len %d" %(datalen,))
str_data = ''
if(datalen > 0):
mask_key = data[2:6]
masked_data = data[6:(6+datalen)]
unmasked_data = [masked_data[i] ^ mask_key[i%4] for i in range(len(masked_data))]
str_data = str(bytearray(unmasked_data))
return str_data
def broadcast_resp(self, data):
# 1st byte: fin bit set. text frame bits set.
# 2nd byte: no mask. length set in 1 byte.
resp = bytearray([0b10000001, len(data)])
# append the data bytes
for d in bytearray(data):
resp.append(d)
self.LOCK.acquire()
for client in self.clients:
try:
client.send(resp)
except:
print("error sending to a client")
self.LOCK.release()
def parse_headers (self, data):
headers = {}
lines = data.splitlines()
for l in lines:
parts = l.split(": ", 1)
if len(parts) == 2:
headers[parts[0]] = parts[1]
headers['code'] = lines[len(lines) - 1]
return headers
def handshake (self, client):
print('Handshaking...')
data = client.recv(2048)
headers = self.parse_headers(data)
print('Got headers:')
for k, v in headers.iteritems():
print k, ':', v
key = headers['Sec-WebSocket-Key']
resp_data = self.HSHAKE_RESP % ((base64.b64encode(hashlib.sha1(key+self.MAGIC).digest()),))
print('Response: [%s]' % (resp_data,))
return client.send(resp_data)
def handle_client (self, client, addr):
self.handshake(client)
try:
while 1:
data = self.recv_data(client)
print("received [%s]" % (data,))
self.broadcast_resp(data)
except Exception as e:
print("Exception %s" % (str(e)))
print('Client closed: ' + str(addr))
self.LOCK.acquire()
self.clients.remove(client)
self.LOCK.release()
client.close()
def start_server (self, port):
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', port))
s.listen(5)
while(1):
print ('Waiting for connection...')
conn, addr = s.accept()
print ('Connection from: ' + str(addr))
threading.Thread(target = self.handle_client, args = (conn, addr)).start()
self.LOCK.acquire()
self.clients.append(conn)
self.LOCK.release()
ws = PyWSock()
ws.start_server(9876)
link
I think minimal server.py
import socket,hashlib,base64
MAGIC = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
HSHAKE_RESP = "HTTP/1.1 101 Switching Protocols\r\n" + \
"Upgrade: websocket\r\n" + \
"Connection: Upgrade\r\n" + \
"Sec-WebSocket-Accept: %s\r\n" + \
"\r\n"
HOST = ''
PORT = 9876
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)
conn, addr = s.accept()
print 'Connected by', addr
data = conn.recv(4096)
headers = {}
lines = data.splitlines()
for l in lines:
parts = l.split(": ", 1)
if len(parts) == 2:
headers[parts[0]] = parts[1]
headers['code'] = lines[len(lines) - 1]
key = headers['Sec-WebSocket-Key']
resp_data = HSHAKE_RESP % ((base64.b64encode(hashlib.sha1(key+MAGIC).digest()),))
conn.send(resp_data)
while 1:
data = conn.recv(4096)
if not data:
break
databyte = bytearray(data)
datalen = (0x7F & databyte[1])
str_data = ''
if(datalen > 0):
mask_key = databyte[2:6]
masked_data = databyte[6:(6+datalen)]
unmasked_data = [masked_data[i] ^ mask_key[i%4] for i in range(len(masked_data))]
str_data = str(bytearray(unmasked_data))
print str_data
resp = bytearray([0b10000001, len(str_data)])
for d in bytearray(str_data):
resp.append(d)
conn.sendall(resp)
conn.close()
One time running. Because not threading.