I am working in a C program with sockets. I found a proxy python script which is working with my program:
import threading
import serial
import socket
def setup():
"""
This function sets up the variables needed, including the serial port,
and it's speed/port settings, listening socket, and localhost adddress.
"""
global clisock, cliaddr, svrsock, ser
# Change this to the COM port your XBee Cellular module is using. On
# Linux, this will be /dev/ttyUSB#
comport = '/dev/ttyAMA0'
# This is the default serial communication speed of the XBee Cellular
# module
comspeed = 9600
buffer_size = 4096 # Default receive size in bytes
debug_on = 0 # Enables printing of debug messages
toval = None # Timeout value for serial port below
# Serial port object for XBCell modem
ser = serial.Serial(comport,comspeed,timeout=toval)
# Listening socket (accepts incoming connection)
svrsock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# Allow address reuse on socket (eliminates some restart errors)
svrsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
clisock = None
cliaddr = None # These are first defined before thread creation
addrtuple = ('localhost', 1881) # Address tuple for localhost
# Binds server socket to localhost (allows client program connection)
svrsock.bind(addrtuple)
svrsock.listen(1) # Allow (1) connection
def ComReaderThread():
"""
This thread listens on the defined serial port object ('ser') for data
from the modem, and upon receipt, sends it out to the client over the
client socket ('clisock').
"""
global clisock
while (1):
resp = ser.read() ## Read any available data from serial port
print("Received {} bytes from modem.".format(len(resp)))
clisock.sendall(resp) # Send RXd data out on client socket
print("Sent {} byte payload out socket to client.".format(len(resp)))
def SockReaderThread():
"""
This thread listens to the MQTT client's socket and upon receiving a
payload, it sends this data out on the defined serial port ('ser') to the
modem for transmission.
"""
global clisock
while (1):
data = clisock.recv(4096) # RX data from client socket
# If the RECV call returns 0 bytes, the socket has closed
if (len(data) == 0):
print("ERROR - socket has closed. Exiting socket reader thread.")
return 1 # Exit the thread to avoid a loop of 0-byte receptions
else:
print("Received {} bytes from client via socket.".format(len(data)))
print("Sending payload to modem...")
bytes_wr = ser.write(data) # Write payload to modem via UART/serial
print("Wrote {} bytes to modem".format(bytes_wr))
def main():
setup() # Setup the serial port and socket
global clisock, svrsock
if (not clisock): # Accept a connection on 'svrsock' to open 'clisock'
print("Awaiting ACCEPT on server sock...")
(clisock,cliaddr) = svrsock.accept() # Accept an incoming connection
print("Connection accepted on socket")
# Make thread for ComReader
comthread = threading.Thread(target=ComReaderThread)
comthread.start() # Start the thread
# Make thread for SockReader
sockthread = threading.Thread(target=SockReaderThread)
sockthread.start() # Start the thread
main()
I tried to do the same proxy script in C
#include "project.h"
#include <sys/socket.h>
#include <arpa/inet.h>
int fd,baudrate=9600,sock,new_socket;
struct sockaddr_in serv_addr, client;
int setup(){
int opt=1;
sock=0;
if(wiringPiSetup() <0) return 1;
if((fd=serialOpen("/dev/ttyAMA0",baudrate))<0) return 1;
printf("Serial communication opened \n");
fflush(stdout);
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
printf("\n Socket creation error \n");
return -1;
}
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR , &opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(1881);
int addrlen = sizeof(struct sockaddr_in);
if (bind(sock, (struct sockaddr *)&serv_addr, addrlen)<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(sock, 1) <0)
{
perror("listen");
exit(EXIT_FAILURE);
}
printf("1\n");
addrlen=sizeof(struct sockaddr_in);
socklen_t sin_size=sizeof(struct sockaddr_in);
if ((new_socket = accept(sock, (struct sockaddr *)&client, &sin_size)) < 0)
{
perror("accept");
exit(EXIT_FAILURE);
}
char *client_ip = inet_ntoa(client.sin_addr);
printf("Accepted new connection from a client %s:%d\n", client_ip, ntohs(client.sin_port));
printf("1\n");
return 0;
}
PI_THREAD(socketRead){
int valread;
char buffer[4096]={0};
printf("hola %i\n",new_socket);
//Nos mantenemos a la escucha
for(;;){
//memset(buffer,0,sizeof(buffer));
//valread = recv( new_socket, buffer, 1024,0);
while((valread = read(new_socket,buffer,sizeof(buffer)-1))>0){
/*if ( valread < 0 ) {
printf ( "An error occured during the receive procedure \n" ) ;
return 0 ;
}*/
buffer[valread]=0;
printf("buffer %s\n",buffer);
write(fd,buffer,strlen(buffer));
}
}
}
PI_THREAD(uartRead){
int valread;
char buffer[4096]={0};
//Nos mantenemos a la escucha
for(;;){
//memset(buffer,0,sizeof(buffer));
valread = read( fd, buffer, sizeof(buffer));
//valread = read(new_socket,buffer,4096);
//send( new_socket, buffer,4096,0);
write(new_socket,buffer,sizeof(buffer));
printf("recibido\n");
}
}
int main(){
setup();
printf("adios %i\n",new_socket);
/* Thread creation */
piThreadCreate (socketRead);
piThreadCreate (uartRead);
for(;;){}
return 0;
}
I have not found differences between both programs, so my question is if there are any differences between Python and C libraries. With Python I am allow to see read the messages but in C I only receive 0x10 and 0x11. So, are there any differences between libraries or is something with my C script?
PI_THREAD(uartRead){
...
char buffer[4096]={0};
...
valread = read( fd, buffer, sizeof(buffer));
...
write(new_socket,buffer,sizeof(buffer));
In this code you read valread byte from the serial line but you always write 4096 byte (sizeof(buffer)). This means you send not only the data from the serial line but lots of junk data which are in the buffer.
The problem is thus not the difference between sockets in Python and C but just a bug in the C program.
Related
I am creating a C server and Python client for UNIX domain datagram sockets (UDS) IPC on Ubuntu 18.04. My scenario is: Python runs as a child process created with fork-execv where C is the parent process. The Python client blocks on socket.recvfrom until data is sent by the C server. When the C server sends data to the Python client then C will block on recvfrom until Python sends data to C with sendto.
I have used UDS for a C client and a C server with no problems, but the C-Python setup is causing some problems. For this Python version I worked from an example at https://lloydrochester.com/post/c/unix-domain-socket-datagram.
I create a server socket in C and bind to it; it returns file descriptor 5:
int64_t * create_socket_server(struct sockaddr_un svaddr, int64_t retvals[])
{
int sfd, j;
ssize_t numBytes;
socklen_t len;
char buf[BUF_SIZE];
retvals[0] = 0;
retvals[1] = 0;
sfd = socket(AF_UNIX, SOCK_DGRAM, 0); /* Create server socket
if (sfd == -1)
return retvals;
if (remove(SV_SOCK_PATH) == -1 && errno != ENOENT)
return retvals;
memset(&svaddr, 0, sizeof(struct sockaddr_un));
svaddr.sun_family = AF_UNIX;
strncpy(svaddr.sun_path, SV_SOCK_PATH, sizeof(svaddr.sun_path) - 1);
if (bind(sfd, (struct sockaddr *) &svaddr, sizeof(struct sockaddr_un)) == -1)
return retvals;
retvals[0] = sfd;
retvals[1] = (int64_t)&svaddr;
return retvals;
}
I do not create or explicitly connect to the client socket on the C side.
On the Python side I bind to the client socket. Here is my Python code, following the example cited, but altered somewhat to fit my use case:
#!/usr/bin/python3
import socket
import os, os.path
csock_file = "/tmp/py_sock"
ssock_file = "/tmp/ud_ucase"
if os.path.exists(csock_file):
os.remove(csock_file)
csock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
csock.bind(csock_file) # Bind to the server socket
return_msg = "Got it"
while True:
(bytes, address) = csock.recvfrom(720)
msg = bytes.decode('utf-8')
print("Python received")
if msg != "Code_99":
print('address:',address,'received:',msg)
csock.sendto(str.encode(return_msg), ssock_file)
if msg == "Code_99":
print("closing")
#Close the socket
I want recvfrom to be blocking in both Python and C because Python should block until C sends, but when I leave it at blocking (the default) then Python blocks both processes when it calls (bytes, address) = csock.recvfrom(720), and C cannot continue.
If I set it to nonblocking with csock.setblocking(False) I get this error message:
(bytes, address) = csock.recvfrom(720)
BlockingIOError: [Errno 11] Resource temporarily unavailable
So my question is why does Python block both processes, and why do I get that error message in nonblocking mode?
Thanks for any help.
Explanation
why does Python block both processes ?
When your client is waiting for your server's response with recvfrom, you server just did nothing, thus server blocks at its recvfrom as well.
why do I get that error message in nonblocking mode ?
Your server/client might not be as robust as the one you quoted (i.e. from lloydrochester.com). Serveral parts broke and result in breaking the whole thing. Some of them are just about C Lang, such as Variable Declarations, Function Returning, etc. Others are about network programming, such as Buffer Sizing, Socket Internals, etc. It's not realistic to list them all and analyse one by one. Better read through K&R and BSD socket to fix them thoroughly.
However, here is an relatively simple implementation for you case, based on your codes, shown below. In addition, you might want to change the reply message to Code_99 in the 48th line of server_alice.c.
Environment
Ubuntu 18.04
gcc 7.5.0
Python 3.6.9
server_alice.c
#include <sys/un.h>
#include <sys/socket.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#define BUF_SIZE 720
#define SV_SOCK_PATH "ssock"
int create_socket_server(int *sfd_ptr, struct sockaddr_un *svaddr_ptr);
int main(int argc, char *argv[]) {
struct sockaddr_un svaddr, claddr;
int sfd, j;
ssize_t numBytes;
socklen_t len;
char buf[BUF_SIZE];
int64_t retvals[2];
if (create_socket_server(&sfd, &svaddr) == 0)
printf("create_socket_server...DONE\n");
else exit(0);
for (;;) {
len = sizeof(struct sockaddr);
printf("waiting clients...\n");
numBytes = recvfrom(sfd, buf, BUF_SIZE, 0, (struct sockaddr *) &claddr, &len);
if (numBytes == -1) {
fprintf(stderr, "error recvfrom");
return 4;
}
claddr.sun_path[len - sizeof(sa_family_t) - 1] = 0;
buf[numBytes] = '\0';
fprintf(stdout, "server received %ld bytes from %s, they are: \x1b[32m%s\x1b[0m\n", (long) numBytes,
claddr.sun_path, buf);
for (j = 0; j < numBytes; j++) {
buf[j] = toupper((unsigned char) buf[j]);
}
// char *reply_msg="Code_99"; # different reply message
char *reply_msg = "Hello Bob~ This is a message: blablablabla";
j = sendto(sfd, reply_msg, strlen(reply_msg), 0, (struct sockaddr *) &claddr, len);
if (j != strlen(reply_msg)) {
fprintf(stderr, "error sendto %s", strerror(errno));
}
}
exit(EXIT_SUCCESS);
}
/* Your create_socket_server, with a few changes */
int create_socket_server(int *sfd_ptr, struct sockaddr_un *svaddr_ptr) {
struct sockaddr_un svaddr;
int sfd = socket(AF_UNIX, SOCK_DGRAM, 0); // Create server socket
if (sfd == -1)
return -1;
if (remove(SV_SOCK_PATH) == -1 && errno != ENOENT)
return -1;
memset(&svaddr, 0, sizeof(struct sockaddr_un));
svaddr.sun_family = AF_UNIX;
strncpy(svaddr.sun_path, SV_SOCK_PATH, sizeof(svaddr.sun_path) - 1);
if (bind(sfd, (struct sockaddr *) &svaddr, sizeof(struct sockaddr_un)) == -1)
return -1;
memcpy(sfd_ptr, &sfd, sizeof(int));
memcpy(svaddr_ptr, &svaddr, sizeof(struct sockaddr_un));
return 0;
}
client_bob.py
#!/usr/bin/python3
import socket
import os, os.path
csock_file = "./csock"
ssock_file = "./ssock"
if os.path.exists(csock_file):
os.remove(csock_file)
csock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
csock.bind(csock_file) # Bind to the server socket
return_msg = "Got it"
csock.sendto(str.encode("Hello Alice! I'm coming!"), ssock_file)
# while True: # ! CATION ! If 'while(true)', there will be infinite message sending back and forth!
(bytes, address) = csock.recvfrom(720)
msg = bytes.decode('utf-8')
if msg != "Code_99":
print('address: ', address, 'received: ', msg)
csock.sendto(str.encode(return_msg), ssock_file)
if msg == "Code_99":
print("closing")
csock.close()
Server Output:
$ gcc server_alice.c && ./a.out
create_socket_server...DONE
waiting clients...
server received 24 bytes from ./csock, they are: Hello Alice! I'm coming!
waiting clients...
server received 6 bytes from ./csock, they are: Got it
waiting clients...
Client Output:
$ python3 client_bob.py
address: ssock received: Hello Bob~ This is a message: blablablabla
I have an ESP32 opening a simple TCP server and a python script accessing as client.
Things are going quite smooth, but when the ESP32 reset (e.g. after a power loss) or when no connection is made directly after powering the ESP, the client cannot connect any more.
ESP Server code, using Arduino Core(shortend):
#include <WiFi.h>
WiFiServer server(23);
void setup() {
server.begin();
}
void loop() {
WiFiClient client = server.available();
if (client) {
if (client.connected()) {
Serial.println("Client connected");
lastConnection = timeNow;
if (client.available()) {
Serial.println("Data to be read");
String line = client.readStringUntil('\n');
Serial.println(line);
}
if (timeSendWs < timeNow) {
Serial.println("Sending data");
String msg = notifyClients(); //notifyClients() build the message that is to be send
char *cmsg = &msg[0];
client.write(cmsg);
timeSendWs = timeNow + TIME_SEND_WS;
}
}
Serial.println("Disconnecting");
client.stop();
}
if (lastConnection < timeNow - 2 * TIME_SEND_WS) {
Serial.println("Connection interrupted for too long");
client.stop();
Stopping(); //Some action that needs to taken, when not connection could be established for some time
lastConnection = timeNow;
}
}
Python script
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)
s.connect(('192.168.2.251', 23))
s.sendall('hi\n'.encode()) # Include \n to ensure faster processing
data = []
while True:
chunk = s.recv(1024)
if not chunk: break # When the other side closes the socket, chunk = ''
data.append(chunk.decode())
all_data = ''.join(data)
if len(all_data) > 0:
print(all_data)
except OSError as e:
print(e)
s.close()
time.sleep(0.1)
The errors I get on python side are either "timeout" or "[Errno 64] Host is down" and just before reconnecting "[Errno 61] Connection refused"
Hello l am new to BSD Socket API programming. I followed the UDP client example on the Wikipedia (https://en.wikipedia.org/wiki/Berkeley_sockets) and l am encountering a strange issue. The packets arrive at my server, but the message inside is cut off. I am looking for the terminology for this problem, and a clue to resolve this issue. Thank you for the assistance.
C Function:
void udp_client_task() {
while(1) {
int sock; struct sockaddr_in sa; char buffer[200];
strcpy(buffer,"My World NEO! This is My World!");
/* create an Internet, datagram, socket using UDP */
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == -1) {
/* if socket failed to initialize, exit */
break;
}
/* Zero out socket address */
memset(&sa, 0, sizeof sa);
/* The address is IPv4 */
sa.sin_family = AF_INET;
/* IPv4 addresses is a uint32_t, convert octets to the appropriate value */
sa.sin_addr.s_addr = inet_addr("192.168.0.5");
/* sockets are unsigned shorts, htons(x) ensures x is in network byte order */
sa.sin_port = htons(139);
bytes_sent = sendto(sock, buffer, strlen(buffer), 0,(struct sockaddr*)&sa, sizeof sa);
// osDelay(500);
close(sock); /* close the socket */
}
Python UDP Server:
import socket
from datetime import datetime
class UDP_Server():
def __init__(self, single_group, port_receive):
self.single_group = single_group
self.port_receive = port_receive
def configure_receive_server(self):
# Define the buffer size for this function
size_buffer = 1024
# Print start of function
msg = 'UDP Receive Inputs: Single Group - {0} ; Port (Receive From) - {1} ; Buffer Size - {2}'.format(self.single_group, self.port_receive, size_buffer)
print(msg)
# Open a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
print("Socket created...")
# Allow port reuse
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
print("Socket allowed reuse...")
# Bind IP Address to Port
print("Binding the IP: {0}".format(self.single_group))
sock.bind((self.single_group, self.port_receive))
while True:
print("------ New Loop ------")
# Receive the client packet along with the address it is coming from
message, address = sock.recvfrom(1024)
print("{0}".format(datetime.now().strftime("%Y-%m-%d_%H:%M:%S")))
msg = 'UDP message received from address - {0} ; \nMessage - {1} ; \nMessage Length - {2}'.format(address, message, len(message))
print(msg)
if __name__ == '__main__':
# Define constants
UDP_IP = "192.168.0.5"
# UDP_group = "192.168.0.5"
port_receive_tlm = 139
# port_receive_tlm = 139
# Initialize the class
commander = UDP_Server(single_group=UDP_IP,
port_receive=port_receive_tlm)
# Listen for a response
# NOTE: This will exit after a certain number of attempts
commander.configure_receive_server()
I'm building a real-time wireless link between a PC base station and a dozen robots, each transmitting at 60Hz.
For testing I wrote a Python script that sends UDP multicast packets over my WiFi network. And then on another multicast group I have two ESP8266 sending replies. One sends at 60Hz to simulate the real set-up, and the other spams at 10 times that rate to simulate congestion from the other devices.
First I only looked at packet loss, which was kind of as expected. But then I started to look at round-trip time. I made my Python script write the current time, and made the "real" node echo them back. (spammer messages are ignored)
With the spammer node turned off I get 10ms round-trip, but with the spammer, it starts at 100ms and slowly grows to over a second.
How can I debug this issue?
I tried to use Wireshark, but since they are separate UDP streams with custom data in them, I could not figure out any sensible analysis.
I figured the packets probably get stuck in a queue somewhere, so some googling suggested you can look at the queue length with the following command. Sure, the queue is not empty, but if I turn the spammer node off, nothing much changes in the queue length, while round-trip drops back to 10ms.
netstat -c --udp -an
Proto Recv-Q Send-Q Local Address Foreign Address State
udp 40256 0 0.0.0.0:8080 0.0.0.0:*
I thought maybe my Python code is just too slow to handle 600 messages per second. Running on PyPy made absolutely no difference, so I'm a bit hesitant to write the whole thing in C. It has almost 2ms per packet to do almost nothing.
Base station code:
import socket
import struct
import sched, time
import threading
base_multicast = '239.255.0.34'
robot_multicast = '239.255.0.35'
port = 8080
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', port))
mreq = struct.pack("4sl", socket.inet_aton(robot_multicast), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
# schedule base station packets
send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
send_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
rate = 1/60
#sock.settimeout(rate)
s = sched.scheduler(time.time, time.sleep)
def send(now):
nxt = now+rate
s.enterabs(nxt, 1, send, argument=(nxt,))
tstr = struct.pack("d", time.time())
send_sock.sendto(tstr, (base_multicast, port))
print(".", end='')
s.enter(1, 1, send, argument=(time.time(),))
t = threading.Thread(target=s.run)
t.daemon = True
t.start()
start = time.time()
avg_dur = 0
avg_ping = 0
while True:
try:
data = sock.recv(10240)
except socket.timeout:
continue
now = time.time()
duration = now-start
start = now
avg_dur = 0.99*avg_dur + 0.01*duration
try:
(t,) = struct.unpack("d", data)
ping = now-t
avg_ping = 0.99*avg_ping + 0.01*ping
print(len(data), 1/avg_dur, avg_ping)
except struct.error: # spammer message
pass
Robot node: (spammer is identical, except it sends replyPacket 10 times in a loop)
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
const char* ssid = "mywifi";
const char* password = "password";
IPAddress base_multicast(239, 255, 0, 34);
IPAddress robot_multicast(239, 255, 0, 35);
WiFiUDP Udp;
unsigned int port = 8080; // local port to listen on
char incomingPacket[255]; // buffer for incoming packets
char replyPacket[] = "Hi there! Got the message :-))))"; // a reply string to send back
int rate = 1000/60;
unsigned long mytime;
unsigned long count;
float avg_diff = 0;
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println(" connected");
//Udp.begin(localUdpPort);
Udp.beginMulticast(WiFi.localIP(), base_multicast, port);
Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), port);
mytime = millis();
}
void loop()
{
int packetSize = Udp.parsePacket();
if (packetSize)
{
// receive incoming UDP packets
unsigned long diff = micros() - mytime;
avg_diff = 0.9*avg_diff + 0.1*diff;
mytime = micros();
int rcv_rate = 1000000/avg_diff;
Serial.println(rcv_rate);
int len = Udp.read(incomingPacket, 255);
delay(random(rate));
//Serial.printf("UDP packet contents: %s\n", incomingPacket);
Udp.beginPacketMulticast(robot_multicast, port, WiFi.localIP());
Udp.write(incomingPacket, len);
Udp.endPacket();
}
}
I am beginner in python written first program two days ago. I am having connection problem in python client and C server for AF_UNIX. I have C socket Server with AF_LOCAL.
#define NAME "#/tmp/kvsd"
int
main()
{
int sock, msgsock, rval;
struct sockaddr_un server;
char buf[1024];
unlink(NAME);
printf("before socket \n");
sock = socket(AF_LOCAL, SOCK_STREAM, 0);
if (sock < 0) {
perror("opening stream socket");
exit(1);
}
memset(&server, 0, (sizeof (server)));
server.sun_family = AF_LOCAL;
memcpy(server.sun_path, NAME, strlen(NAME));
server.sun_path[0] = 0;
printf("before bind \n");
int len = strlen(server.sun_path) + sizeof(server.sun_family);
if (bind(sock, (struct sockaddr *) &server, len)) {
perror("binding stream socket");
exit(1);
}
printf("before listen \n");
if (listen(sock, 5) == -1) {
perror("listen");
exit(1);
}
printf("before accept \n");
msgsock = accept(sock, 0, 0);
printf("accepted \n");
if (msgsock == -1)
perror("accept");
else do {
bzero(buf, sizeof(buf));
printf("before read \n");
if ((rval = read(msgsock, buf, 1024)) < 0)
perror("reading stream message");
else if (rval == 0)
printf("Ending connection\n");
else
printf("-->%s\n", buf);
} while (rval > 0);
close(msgsock);
close(sock);
unlink(NAME);
}
And Python AF_UNIX client.py:-
####### CLIENT CODE #######
from socket import *
# Create an unbond and not-connected socket.
sock = socket(AF_UNIX, SOCK_STREAM)
# Connect to the peer registered as "MyBindName" in the abstract namespace. Note the '\0'.
str = "\0/tmp/kvsd\0"
print "len ", len (str)
sock.connect("\0/tmp/kvsd")
# Wait for message
msg = sock.recv(100)
print msg
# Send reply
sock.send("Hi there!\n")
# Block until new message arrives
msg = sock.recv(100)
# When the socket is closed cleanly, recv unblocks and returns ""
if not msg:
print "It seems the other side has closed its connection"
# Close it
sock.close()
But When I run the client I'm getting following error:
[root#mat afunix]# python ./client.py len 11 Traceback (most recent call last): File "./client.py", line 13, in sock.connect("\0/tmp/kvsd") File "", line 1, in connect socket.error: [Errno 111] Connection refused [root#mat afunix]#
I am trying to use the abstract namespaces for UNIX socket but my python client is not able to connect to c server.
I tried without abstract namespaces it works. (changed NAME macro in server.c to "/tmp/kvsd" and argument to sock.connect to "/tmp/kvsd").
Can someone help me to figure out what may be the exact issue ?
Thanks in advance.
Following line has a problem.
int len = strlen(server.sun_path) + sizeof(server.sun_family);
server.sun_path has now leading null character. So strlen(server.sun_path) is 0. You need change above line as follow:
#include <stddef.h>
....
int len = offsetof(struct sockaddr_un, sun_path) + strlen(NAME);
Then, it will work.
EDIT: updated the code to use offsetof to avoid padding issue. (Thank you, alk)
PS: I assume that both server, client use name without trailing null byte. If you use name with trailing null byte, add 1 to len.