Python AF_UNIX client C server - python

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.

Related

Sending const char* through UDP server

I am trying to implement a basic UDP socket in my code to send a string. Created an UDP server in C++ to send sort of a "hello world" and a client in Python to receive it. For this, I'm using G4G's example as base, only slightly modified:
#define PORT xxxx
void initializeUDP(int stop) {
int sockfd;
const char *hello = "Hello from server.\n";
struct sockaddr_in servaddr, cliaddr;
//Initialize Winsock
WSADATA data;
WORD version = MAKEWORD(2, 2);
int wsOk = WSAStartup(version, &data);
if (wsOk != 0) {
cout << "Cannot start Winsock! " << wsOk;
return;
}
// Creating socket and binding with address
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));
servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
if (::bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
int len;
len = sizeof(cliaddr); //len is value/result
while (globalVariableNameInPortuguese == 0) {
sendto(sockfd, (const char *)hello, 1024, 0, (const struct sockaddr *) &cliaddr, len);
}
closesocket(sockfd);
WSACleanup();
}
Also created these few lines to try to receive this string as a client in Python:
import socket
bufferSize = 1024
ip = "localhost"
port = xxxx
UDPClientSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
UDPClientSocket.connect((ip, port))
while True:
message, address = UDPClientSocket.recvfrom(bufferSize)
print(message)
UDPClientSocket.close()
The C++ code executes normally but I am uncertain whether it's actually doing what it should. However, if I set the IP in the Python code as "localhost" it gets stuck in recvfrom, and if I set the IP to 0.0.0.0 it gets WinError 10049. Not sure on what I'm doing wrong and how I should proceed to actually get this string.

Using sockets to send a string from a C++ client on one computer to a Python server on another. Getting `send: Bad file descriptor`

I'm trying to send a string from a C++ client on one computer to a Python server on another computer.
My error is send: Bad file descriptor
The Python server is killed if it is contacted by the client but it doesn't receive a string. While the Python server is running it does end the program when I attempt to send the string from the C++ client. So I know the server is being reached by the client when I execute it.
I am able to send strings to the server from the C++ client's computer with a Python client script. Since it's not a basic problem with the server I don't think this and other answers apply to my problem.
On the Python script I have tried changing this number.
s.listen(11)
Here is the Python server
import os
import sys
import socket
s=socket.socket()
host='192.168.0.101'
port=12003
s.bind((host,port))
s.listen(11)
while True:
c, addr=s.accept()
content=c.recv(1024).decode('utf-8')
print(content)
if not content:
break
Here is the C++ client
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <unistd.h>
#define ADDR "192.168.0.101"
#define PORT "12003"
void sendall(int socket, char *bytes, int length)
{
int n = 0, total = 0;
while (total < length) {
n = send(socket, bytes + total, total-length, 0);
if (n == -1) {
perror("send");
exit(1);
}
total += n;
}
}
int main()
{
struct addrinfo hints = {0}, *addr = NULL;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int status = getaddrinfo(ADDR, PORT, &hints, &addr);
if (status != 0) {
fprintf(stderr, "getaddrinfo()\n");
exit(1);
}
int sock = -1;
{
struct addrinfo *p = NULL;
for (p = addr; p != NULL; p = addr->ai_next) {
int sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sock == -1) {
continue;
}
if (connect(sock, p->ai_addr, p->ai_addrlen) != -1) {
break;
}
close(sock);
}
if (p == NULL) {
fprintf(stderr, "connect(), socket()\n");
exit(1);
}
freeaddrinfo(addr);
/* Do whatever. */
sendall(sock, "Hello, World", 12);
/* Do whatever. */
}
close(sock);
return 0;
}
UPDATE:
In the client there was an unessacary int in front of sock = socket...
I removed it and now I'm getting an error on the server side when I send the string that reads..
$ python server.py
Traceback (most recent call last):
File "/home/computer/server.py", line 35, in <module>
content=c.recv(1024).decode('utf-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfc in position 29: invalid start byte
You're redeclaring the sock variable in the for loop, so the value of sock when you call sendall() is the original -1. Change
int sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
to
sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
so it assigns the outer variable.

C socket server and Python socket client "Resource temporarily unavailable"

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

Differences between C and Python sockets

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.

Why client/server mechanism (using socket's) doesn't work?

I have free account on www.pythonanywhere.com. I have a server written on c++
some_space::socket_server::socket_server(unsigned int port):
m_port(port),
m_tcp_fd(0),
m_udp_fd(0),
m_newfd(0)
{
m_addr.sin_family = AF_INET;
m_addr.sin_addr.s_addr = htonl(INADDR_ANY);
m_addr.sin_port = htons(m_port);
}
void some_space::socket_server::set_port(unsigned int port)
{
assert(port != 0);
m_port = port;
}
int some_space::socket_server::create_tcp_connection()
{
m_tcp_fd = socket(AF_INET, SOCK_STREAM, 0);
if(m_tcp_fd < 0) {
perror("Error: Cannot set up the communication");
return -1;
}
int status = bind(m_tcp_fd, (struct sockaddr *)&m_addr, sizeof(m_addr)); if(status < 0) {
perror("Error: Cannot set up the communication");
return -1;
}
status = listen(m_tcp_fd, 5);
if(status == 0) {
m_newfd = accept(m_tcp_fd, (struct sockaddr*)NULL, NULL);// ####################### The code freezes here (on the accept)
if(m_newfd != -1) {
return m_newfd;
}
perror("Error: Cannot accept the connection");
return -1;
}
perror("Error: The port cannot be listened");
return -1;
}
Where m_port = 9999
This cod is runed on .pythonanywhere.com server terminal.
And in the main.
some_space::socket_server* s = new some_space::socket_server(9999);
assert(s != 0);
int r = s->create_tcp_connection(); // it it freezes in this function
assert(r != -1);
std::string rsp("");
s->recv_response(rsp);
std::string rec("some data");
const char* t = rec.c_str();
char* buf = const_cast<char*>(t);
int size = rec.length();
r = s->send_data(buf, size);
assert(r != -1);*/
.......................
Also, I have a client program in my local pc written on python.
#!/usr/bin/env python
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('<username>.pythonanywhere.com', 9999))
sock.send('hello, world!')
data = sock.recv(1024)
print "receive >>> %s" % data
sock.close()
But the problem is the client can't connect with the server, it waits always. Where is a problem?
PythonAnywhere dev here: PythonAnywhere only supports web apps using the Python WSGI protocol, which covers almost all of the main Python web frameworks (Django, web2py, Flask, Bottle, etc) but won't work with your own C-based server.

Categories

Resources