如何用Python Socket接收POSIX Socket发送的浮点数值
Got it, let's work through this problem step by step. The core issue here is ensuring your C and Python code align on byte order (endianness) and how float values are packed into bytes—mismatches here will lead to unreadable garbage when converting on the Python side.
Step 1: C Side (POSIX Socket Sender)
We'll convert each float to a 32-bit unsigned integer, then use htonl() to standardize it to network byte order (big-endian) before sending. This ensures consistency regardless of the C machine's native endianness.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdint.h> #define PORT 8080 #define NUM_FLOATS 8 // Convert float to network byte order (big-endian) uint32_t float_to_network(float f) { uint32_t raw_val; // Copy float bytes into a 32-bit integer memcpy(&raw_val, &f, sizeof(raw_val)); // Convert to network big-endian return htonl(raw_val); } int main() { int sock_fd = socket(AF_INET, SOCK_STREAM, 0); if (sock_fd < 0) { perror("Failed to create socket"); exit(EXIT_FAILURE); } struct sockaddr_in server_addr = {0}; server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); // Replace with your Python server's IP if not local if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) { perror("Invalid server IP"); close(sock_fd); exit(EXIT_FAILURE); } if (connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { perror("Failed to connect to server"); close(sock_fd); exit(EXIT_FAILURE); } // Your float array float float_data[NUM_FLOATS] = {1.5f, 2.7f, 3.9f, 4.2f, 5.6f, 6.1f, 7.3f, 8.8f}; uint32_t network_data[NUM_FLOATS]; // Convert all floats to network byte order for (int i = 0; i < NUM_FLOATS; i++) { network_data[i] = float_to_network(float_data[i]); } // Send the entire array (8 floats = 32 bytes total) ssize_t bytes_sent = send(sock_fd, network_data, sizeof(network_data), 0); if (bytes_sent != sizeof(network_data)) { perror("Failed to send all data"); close(sock_fd); exit(EXIT_FAILURE); } printf("Successfully sent %d float values\n", NUM_FLOATS); close(sock_fd); return 0; }
Step 2: Python Side (Socket Receiver)
We'll use Python's struct module to unpack the received bytes back into floats. We explicitly use network byte order (big-endian) to match the C side's conversion. Also, we ensure we receive the full 32 bytes (8 floats × 4 bytes each) since TCP can split data into chunks.
import socket import struct PORT = 8080 NUM_FLOATS = 8 TOTAL_BYTES = NUM_FLOATS * 4 # 8 floats × 4 bytes each # Set up TCP socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('0.0.0.0', PORT)) server_socket.listen(1) print(f"Waiting for C client on port {PORT}...") conn, client_addr = server_socket.accept() print(f"Connected to {client_addr}") # Receive full data payload (handle partial receives) received_data = b"" while len(received_data) < TOTAL_BYTES: chunk = conn.recv(TOTAL_BYTES - len(received_data)) if not chunk: break # Connection closed prematurely received_data += chunk # Unpack bytes into floats: '!' = network big-endian, '8f' = 8 float values float_array = struct.unpack('!8f', received_data) # Convert tuple to list if needed: float_array = list(float_array) print("Received float array:", float_array) conn.close() server_socket.close()
Key Notes to Avoid Issues
- Byte Order Consistency: Using
htonl()in C and!in Python's struct format ensures your code works across different architectures (x86 is little-endian, some ARM systems are big-endian). - Full Data Receive: TCP doesn't guarantee that
recv()gets all data in one call—always loop until you receive the exact number of bytes you expect. - Float Size: We assume 32-bit (single-precision) floats, which is standard for C's
floattype and Python'sstructmodule'sfformat specifier. If you're using 64-bit doubles, adjust todin Python anddoublein C, with 8 bytes per value.
内容的提问来源于stack exchange,提问作者shashi gouda

