Skip to content

Instantly share code, notes, and snippets.

@xicocana
Forked from marcom04/.python-c-echo
Created July 12, 2020 01:21
Show Gist options
  • Save xicocana/72b167a446454404f8a28e535e02f8b0 to your computer and use it in GitHub Desktop.
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
Basic echo between Python client and C server via socket using Python ctypes
#!/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()
#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