|
3 | 3 | import ubinascii |
4 | 4 | from websocket import websocket |
5 | 5 | import time |
| 6 | +import select |
| 7 | +import gc |
| 8 | + |
| 9 | +# Log memory usage |
| 10 | +def log_memory(): |
| 11 | + gc.collect() |
| 12 | + print('Free memory:', gc.mem_free()) |
6 | 13 |
|
7 | 14 | # Connect to Wi-Fi (disabled as per your code) |
8 | 15 | if False: |
|
14 | 21 | print('Connected:', wlan.ifconfig()) |
15 | 22 |
|
16 | 23 | # Resolve hostname |
17 | | -# Option 1: echo.websocket.events (unreliable) |
18 | | -host = 'echo.websocket.events' |
| 24 | +# Option 1: ws.postman-echo.com (recommended for reliable echo) |
| 25 | +host = 'ws.postman-echo.com' |
19 | 26 | port = 443 |
20 | | -handshake_path = '/' |
21 | | -# Option 2: ws.postman-echo.com (recommended for testing) |
22 | | -# host = 'ws.postman-echo.com' |
23 | | -# port = 443 |
24 | | -# handshake_path = '/raw' |
| 27 | +handshake_path = '/raw' |
| 28 | +# Option 2: echo.websocket.events (unreliable) |
| 29 | +# host = 'echo.websocket.events' |
| 30 | +# handshake_path = '/' |
25 | 31 |
|
26 | 32 | try: |
27 | 33 | addr_info = socket.getaddrinfo(host, port)[0][-1] |
|
44 | 50 | try: |
45 | 51 | ssl_sock = ssl.wrap_socket(sock, server_hostname=host) |
46 | 52 | print('SSL connection established') |
| 53 | + print('SSL cipher:', ssl_sock.cipher()) |
47 | 54 | except Exception as e: |
48 | 55 | print('SSL wrap failed:', e) |
49 | 56 | sock.close() |
50 | 57 | raise |
| 58 | +log_memory() |
51 | 59 |
|
52 | 60 | # Set socket to non-blocking |
53 | 61 | ssl_sock.setblocking(False) |
|
74 | 82 | print('Failed to send handshake:', e) |
75 | 83 | ssl_sock.close() |
76 | 84 | raise |
| 85 | +log_memory() |
77 | 86 |
|
78 | | -# Read HTTP response until \r\n\r\n (minimize reading) |
| 87 | +# Read HTTP response until \r\n\r\n |
79 | 88 | response_bytes = bytearray() |
80 | 89 | max_read = 1024 |
81 | | -read_timeout = 2 |
| 90 | +read_timeout = 5 # Increased to 5s for server response |
82 | 91 | start_time = time.time() |
| 92 | +poller = select.poll() |
| 93 | +poller.register(ssl_sock, select.POLLIN) |
83 | 94 | while len(response_bytes) < max_read: |
| 95 | + events = poller.poll(100) # Wait 100ms |
| 96 | + print('Poll events:', events) |
| 97 | + if not events: |
| 98 | + if time.time() - start_time > read_timeout: |
| 99 | + print('Read timeout reached') |
| 100 | + break |
| 101 | + continue |
84 | 102 | try: |
85 | 103 | chunk = ssl_sock.read(128) |
| 104 | + print('Read attempt, chunk:', chunk) |
| 105 | + if chunk is None: |
| 106 | + print('Read returned None, continuing to poll') |
| 107 | + continue |
86 | 108 | if not chunk: |
87 | 109 | print('No more data received (EOF)') |
88 | 110 | break |
|
91 | 113 | print('Total bytes received:', len(response_bytes)) |
92 | 114 | if b'\r\n\r\n' in response_bytes: |
93 | 115 | print('End of HTTP headers detected') |
94 | | - # Decode and verify HTTP response immediately |
95 | 116 | http_end = response_bytes.find(b'\r\n\r\n') + 4 |
96 | 117 | if http_end < 4: |
97 | 118 | ssl_sock.close() |
|
110 | 131 | print('Handshake response:', response) |
111 | 132 | ssl_sock.close() |
112 | 133 | raise Exception('Handshake failed') |
113 | | - # Stop reading to leave WebSocket frame in socket buffer |
114 | 134 | print('Stopping read to preserve WebSocket frame') |
115 | 135 | break |
116 | 136 | except Exception as e: |
117 | 137 | print('Error reading chunk:', e) |
118 | 138 | break |
119 | | - if time.time() - start_time > read_timeout: |
120 | | - print('Read timeout reached') |
121 | | - break |
| 139 | +log_memory() |
122 | 140 |
|
123 | 141 | # Create WebSocket object |
124 | 142 | try: |
|
128 | 146 | print('Failed to create WebSocket object:', e) |
129 | 147 | ssl_sock.close() |
130 | 148 | raise |
| 149 | +log_memory() |
131 | 150 |
|
132 | | -# Send and receive data with retries |
| 151 | +# Send and receive data with polling |
133 | 152 | try: |
134 | 153 | bytes_written = ws.write('Hello, Secure WebSocket!') |
135 | 154 | print('Sent message, bytes written:', bytes_written) |
|
138 | 157 | ws.close() |
139 | 158 | raise |
140 | 159 |
|
141 | | -# Try reading multiple times to catch initial message or echo |
142 | | -max_attempts = 5 |
143 | | -read_timeout = 1 # Short timeout per read |
| 160 | +# Poll for data with retries |
| 161 | +max_attempts = 10 # Increased retries |
| 162 | +poll_timeout = 100 # 100ms per poll |
| 163 | +start_time = time.time() |
144 | 164 | for attempt in range(max_attempts): |
| 165 | + events = poller.poll(poll_timeout) |
| 166 | + print('Read poll attempt', attempt + 1, 'events:', events) |
| 167 | + if not events: |
| 168 | + print('Read attempt', attempt + 1, 'no data available') |
| 169 | + if time.time() - start_time > 2: # 2s total timeout |
| 170 | + print('Read timeout reached') |
| 171 | + break |
| 172 | + continue |
145 | 173 | try: |
146 | 174 | data = ws.read(1024) |
147 | 175 | print('Read attempt', attempt + 1, 'received:', data) |
148 | 176 | if data: |
149 | 177 | break |
150 | | - time.sleep(0.5) # Wait briefly before retrying |
151 | 178 | except Exception as e: |
152 | 179 | print('Read attempt', attempt + 1, 'error:', e) |
153 | | - time.sleep(0.5) |
154 | | - if time.time() - start_time > read_timeout: |
155 | | - print('Read timeout reached') |
156 | | - break |
| 180 | + time.sleep(0.1) |
157 | 181 |
|
158 | 182 | # Close connection |
159 | 183 | ws.close() |
160 | 184 | print('Connection closed') |
| 185 | +log_memory() |
0 commit comments