-
-
Save xicocana/72b167a446454404f8a28e535e02f8b0 to your computer and use it in GitHub Desktop.
Basic echo between Python client and C server via socket using Python ctypes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Basic echo between Python client and C server via socket using Python ctypes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
""" client.py - Echo client for sending/receiving C-like structs via socket | |
References: | |
- Ctypes fundamental data types: https://docs.python.org/2/library/ctypes.html#ctypes-fundamental-data-types-2 | |
- Ctypes structures: https://docs.python.org/2/library/ctypes.html#structures-and-unions | |
- Sockets: https://docs.python.org/2/howto/sockets.html | |
""" | |
import socket | |
import sys | |
import random | |
from ctypes import * | |
""" This class defines a C-like struct """ | |
class Payload(Structure): | |
_fields_ = [("id", c_uint32), | |
("counter", c_uint32), | |
("temp", c_float)] | |
def main(): | |
server_addr = ('localhost', 2300) | |
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
if s < 0: | |
print "Error creating socket" | |
try: | |
s.connect(server_addr) | |
print "Connected to %s" % repr(server_addr) | |
except: | |
print "ERROR: Connection to %s refused" % repr(server_addr) | |
sys.exit(1) | |
try: | |
for i in range(5): | |
print "" | |
payload_out = Payload(1, i, random.uniform(-10, 30)) | |
print "Sending id=%d, counter=%d, temp=%f" % (payload_out.id, | |
payload_out.counter, | |
payload_out.temp) | |
nsent = s.send(payload_out) | |
# Alternative: s.sendall(...): coontinues to send data until either | |
# all data has been sent or an error occurs. No return value. | |
print "Sent %d bytes" % nsent | |
buff = s.recv(sizeof(Payload)) | |
payload_in = Payload.from_buffer_copy(buff) | |
print "Received id=%d, counter=%d, temp=%f" % (payload_in.id, | |
payload_in.counter, | |
payload_in.temp) | |
finally: | |
print "Closing socket" | |
s.close() | |
if __name__ == "__main__": | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sys/socket.h> | |
#include <arpa/inet.h> //inet_addr | |
#include <unistd.h> //write | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#pragma pack(1) | |
typedef struct payload_t { | |
uint32_t id; | |
uint32_t counter; | |
float temp; | |
} payload; | |
#pragma pack() | |
int createSocket(int port) | |
{ | |
int sock, err; | |
struct sockaddr_in server; | |
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) | |
{ | |
printf("ERROR: Socket creation failed\n"); | |
exit(1); | |
} | |
printf("Socket created\n"); | |
bzero((char *) &server, sizeof(server)); | |
server.sin_family = AF_INET; | |
server.sin_addr.s_addr = INADDR_ANY; | |
server.sin_port = htons(port); | |
if (bind(sock, (struct sockaddr *)&server , sizeof(server)) < 0) | |
{ | |
printf("ERROR: Bind failed\n"); | |
exit(1); | |
} | |
printf("Bind done\n"); | |
listen(sock , 3); | |
return sock; | |
} | |
void closeSocket(int sock) | |
{ | |
close(sock); | |
return; | |
} | |
void sendMsg(int sock, void* msg, uint32_t msgsize) | |
{ | |
if (write(sock, msg, msgsize) < 0) | |
{ | |
printf("Can't send message.\n"); | |
closeSocket(sock); | |
exit(1); | |
} | |
printf("Message sent (%d bytes).\n", msgsize); | |
return; | |
} | |
int main() | |
{ | |
int PORT = 2300; | |
int BUFFSIZE = 512; | |
char buff[BUFFSIZE]; | |
int ssock, csock; | |
int nread; | |
struct sockaddr_in client; | |
int clilen = sizeof(client); | |
ssock = createSocket(PORT); | |
printf("Server listening on port %d\n", PORT); | |
while (1) | |
{ | |
csock = accept(ssock, (struct sockaddr *)&client, &clilen); | |
if (csock < 0) | |
{ | |
printf("Error: accept() failed\n"); | |
continue; | |
} | |
printf("Accepted connection from %s\n", inet_ntoa(client.sin_addr)); | |
bzero(buff, BUFFSIZE); | |
while ((nread=read(csock, buff, BUFFSIZE)) > 0) | |
{ | |
printf("\nReceived %d bytes\n", nread); | |
payload *p = (payload*) buff; | |
printf("Received contents: id=%d, counter=%d, temp=%f\n", | |
p->id, p->counter, p->temp); | |
printf("Sending it back.. "); | |
sendMsg(csock, p, sizeof(payload)); | |
} | |
printf("Closing connection to client\n"); | |
printf("----------------------------\n"); | |
closeSocket(csock); | |
} | |
closeSocket(ssock); | |
printf("bye"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment