UNIX domain sockets
UNIX domain sockets enable efficient communication between processes that are running on the same z/TPF processor. UNIX domain sockets support both stream-oriented, TCP, and datagram-oriented, UDP, protocols. You cannot start a UNIX domain socket for raw socket protocols.
You can issue all of the socket application programming interfaces (APIs) that are supported by the z/TPF system for UNIX domain sockets.
To create a UNIX domain socket, use the socket function and specify AF_UNIX as the domain for the socket. The z/TPF system supports a maximum number of 16,383 active UNIX domain sockets at any time. After a UNIX domain socket is created, you must bind the socket to a unique file path by using the bind function. Unlike internet sockets in the AF_INET domain where the socket is bound to a unique IP address and port number, a UNIX domain socket is bound to a file path.
#define UNIX_PATH_MAX 108
struct sockaddr_un {
unsigned short int sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
};
When you bind a unique name to a UNIX domain socket by using the bind function, a file is created on the file system for the socket. The socket file is at the path that you specify in the SUN_PATH field of the SOCKADDR_UN structure. When the program closes and the file is no longer required, you must manually delete the socket file from the file system.
- Memory file system (MFS)
- Pool file system (PFS)
- Fixed file system (FFS)
If you create UNIX domain sockets, the sockets can be inherited by a child
process that is created by using the fork function.
For internet sockets, the z/TPF system has a concept of
kernel-based sockets, which means that the internet sockets are not bound to a process. However,
UNIX domain sockets are treated as process scoped; that
is, the socket is cleaned up when the last process exits or when all processes issue a close function on the socket.
If you issue the ZIPDB command, the ZSTAT command, or the ZTTCP DISPLAY command with the STATS parameter specified, information about the messages, bytes, and packet counters of the network services database are not updated for UNIX domain sockets. Messages that are sent across UNIX domain sockets are also not displayed in the IP trace facility.
Examples: Server programs that use UNIX domain sockets
/************************************************************/
/* This is a stream socket server sample program for UNIX */
/* domain sockets. This program listens for a connection */
/* from a client program, accepts it, reads data from the */
/* client, then sends data back to connected UNIX socket. */
/************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SOCK_PATH "tpf_unix_sock.server"
#define DATA "Hello from server"
int main(void){
int server_sock, client_sock, len, rc;
int bytes_rec = 0;
struct sockaddr_un server_sockaddr;
struct sockaddr_un client_sockaddr;
char buf[256];
int backlog = 10;
memset(&server_sockaddr, 0, sizeof(struct sockaddr_un));
memset(&client_sockaddr, 0, sizeof(struct sockaddr_un));
memset(buf, 0, 256);
/**************************************/
/* Create a UNIX domain stream socket */
/**************************************/
server_sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (server_sock == -1){
printf("SOCKET ERROR: %d\n", sock_errno());
exit(1);
}
/***************************************/
/* Set up the UNIX sockaddr structure */
/* by using AF_UNIX for the family and */
/* giving it a filepath to bind to. */
/* */
/* Unlink the file so the bind will */
/* succeed, then bind to that file. */
/***************************************/
server_sockaddr.sun_family = AF_UNIX;
strcpy(server_sockaddr.sun_path, SOCK_PATH);
len = sizeof(server_sockaddr);
unlink(SOCK_PATH);
rc = bind(server_sock, (struct sockaddr *) &server_sockaddr, len);
if (rc == -1){
printf("BIND ERROR: %d\n", sock_errno());
close(server_sock);
exit(1);
}
/*********************************/
/* Listen for any client sockets */
/*********************************/
rc = listen(server_sock, backlog);
if (rc == -1){
printf("LISTEN ERROR: %d\n", sock_errno());
close(server_sock);
exit(1);
}
printf("socket listening...\n");
/*********************************/
/* Accept an incoming connection */
/*********************************/
client_sock = accept(server_sock, (struct sockaddr *) &client_sockaddr, &len);
if (client_sock == -1){
printf("ACCEPT ERROR: %d\n", sock_errno());
close(server_sock);
close(client_sock);
exit(1);
}
/****************************************/
/* Get the name of the connected socket */
/****************************************/
len = sizeof(client_sockaddr);
rc = getpeername(client_sock, (struct sockaddr *) &client_sockaddr, &len);
if (rc == -1){
printf("GETPEERNAME ERROR: %d\n", sock_errno());
close(server_sock);
close(client_sock);
exit(1);
}
else {
printf("Client socket filepath: %s\n", client_sockaddr.sun_path);
}
/************************************/
/* Read and print the data */
/* incoming on the connected socket */
/************************************/
printf("waiting to read...\n");
bytes_rec = recv(client_sock, buf, sizeof(buf), 0);
if (bytes_rec == -1){
printf("RECV ERROR: %d\n", sock_errno());
close(server_sock);
close(client_sock);
exit(1);
}
else {
printf("DATA RECEIVED = %s\n", buf);
}
/******************************************/
/* Send data back to the connected socket */
/******************************************/
memset(buf, 0, 256);
strcpy(buf, DATA);
printf("Sending data...\n");
rc = send(client_sock, buf, strlen(buf), 0);
if (rc == -1) {
printf("SEND ERROR: %d", sock_errno());
close(server_sock);
close(client_sock);
exit(1);
}
else {
printf("Data sent!\n");
}
/******************************/
/* Close the sockets and exit */
/******************************/
close(server_sock);
close(client_sock);
return 0;
}
/************************************************************/
/* This is a datagram socket server sample program for UNIX */
/* domain sockets. This program creates a socket and */
/* receives data from a client. */
/************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SOCK_PATH "tpf_unix_sock.server"
int main(void){
int server_sock, len, rc;
int bytes_rec = 0;
struct sockaddr_un server_sockaddr, peer_sock;
char buf[256];
memset(&server_sockaddr, 0, sizeof(struct sockaddr_un));
memset(buf, 0, 256);
/****************************************/
/* Create a UNIX domain datagram socket */
/****************************************/
server_sock = socket(AF_UNIX, SOCK_DGRAM, 0);
if (server_sock == -1){
printf("SOCKET ERROR = %d", sock_errno());
exit(1);
}
/***************************************/
/* Set up the UNIX sockaddr structure */
/* by using AF_UNIX for the family and */
/* giving it a filepath to bind to. */
/* */
/* Unlink the file so the bind will */
/* succeed, then bind to that file. */
/***************************************/
server_sockaddr.sun_family = AF_UNIX;
strcpy(server_sockaddr.sun_path, SOCK_PATH);
len = sizeof(server_sockaddr);
unlink(SOCK_PATH);
rc = bind(server_sock, (struct sockaddr *) &server_sockaddr, len);
if (rc == -1){
printf("BIND ERROR = %d", sock_errno());
close(server_sock);
exit(1);
}
/****************************************/
/* Read data on the server from clients */
/* and print the data that was read. */
/****************************************/
printf("waiting to recvfrom...\n");
bytes_rec = recvfrom(server_sock, buf, 256, 0, (struct sockaddr *) &peer_sock, &len);
if (bytes_rec == -1){
printf("RECVFROM ERROR = %d", sock_errno());
close(server_sock);
exit(1);
}
else {
printf("DATA RECEIVED = %s\n", buf);
}
/*****************************/
/* Close the socket and exit */
/*****************************/
close(server_sock);
return 0;
}
Examples: Client programs that use UNIX domain sockets
/************************************************************/
/* This is a stream socket client sample program for UNIX */
/* domain sockets. This program creates a socket, connects */
/* to a server, sends data, then receives and prints a */
/* message from the server. */
/************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SERVER_PATH "tpf_unix_sock.server"
#define CLIENT_PATH "tpf_unix_sock.client"
#define DATA "Hello from client"
int main(void){
int client_sock, rc, len;
struct sockaddr_un server_sockaddr;
struct sockaddr_un client_sockaddr;
char buf[256];
memset(&server_sockaddr, 0, sizeof(struct sockaddr_un));
memset(&client_sockaddr, 0, sizeof(struct sockaddr_un));
/**************************************/
/* Create a UNIX domain stream socket */
/**************************************/
client_sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (client_sock == -1) {
printf("SOCKET ERROR = %d\n", sock_errno());
exit(1);
}
/***************************************/
/* Set up the UNIX sockaddr structure */
/* by using AF_UNIX for the family and */
/* giving it a filepath to bind to. */
/* */
/* Unlink the file so the bind will */
/* succeed, then bind to that file. */
/***************************************/
client_sockaddr.sun_family = AF_UNIX;
strcpy(client_sockaddr.sun_path, CLIENT_PATH);
len = sizeof(client_sockaddr);
unlink(CLIENT_PATH);
rc = bind(client_sock, (struct sockaddr *) &client_sockaddr, len);
if (rc == -1){
printf("BIND ERROR: %d\n", sock_errno());
close(client_sock);
exit(1);
}
/***************************************/
/* Set up the UNIX sockaddr structure */
/* for the server socket and connect */
/* to it. */
/***************************************/
server_sockaddr.sun_family = AF_UNIX;
strcpy(server_sockaddr.sun_path, SERVER_PATH);
rc = connect(client_sock, (struct sockaddr *) &server_sockaddr, len);
if(rc == -1){
printf("CONNECT ERROR = %d\n", sock_errno());
close(client_sock);
exit(1);
}
/************************************/
/* Copy the data to the buffer and */
/* send it to the server socket. */
/************************************/
strcpy(buf, DATA);
printf("Sending data...\n");
rc = send(client_sock, buf, strlen(buf), 0);
if (rc == -1) {
printf("SEND ERROR = %d\n", sock_errno());
close(client_sock);
exit(1);
}
else {
printf("Data sent!\n");
}
/**************************************/
/* Read the data sent from the server */
/* and print it. */
/**************************************/
printf("Waiting to recieve data...\n");
memset(buf, 0, sizeof(buf));
rc = recv(client_sock, buf, sizeof(buf));
if (rc == -1) {
printf("RECV ERROR = %d\n", sock_errno());
close(client_sock);
exit(1);
}
else {
printf("DATA RECEIVED = %s\n", buf);
}
/******************************/
/* Close the socket and exit. */
/******************************/
close(client_sock);
return 0;
}
/************************************************************/
/* This is a datagram socket client sample program for UNIX */
/* domain sockets. This program creates a socket and sends */
/* data to a server. */
/************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SERVER_PATH "tpf_unix_sock.server"
#define DATA "Hello from client\n"
int main(void)
{
int client_socket, rc;
struct sockaddr_un remote;
char buf[256];
memset(&remote, 0, sizeof(struct sockaddr_un));
/****************************************/
/* Create a UNIX domain datagram socket */
/****************************************/
client_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
if (client_socket == -1) {
printf("SOCKET ERROR = %d\n", sock_errno());
exit(1);
}
/***************************************/
/* Set up the UNIX sockaddr structure */
/* by using AF_UNIX for the family and */
/* giving it a filepath to send to. */
/***************************************/
remote.sun_family = AF_UNIX;
strcpy(remote.sun_path, SERVER_PATH);
/***************************************/
/* Copy the data to be sent to the */
/* buffer and send it to the server. */
/***************************************/
strcpy(buf, DATA);
printf("Sending data...\n");
rc = sendto(client_socket, buf, strlen(buf), 0, (struct sockaddr *) &remote, sizeof(remote));
if (rc == -1) {
printf("SENDTO ERROR = %d\n", sock_errno());
close(client_sock);
exit(1);
}
else {
printf("Data sent!\n");
}
/*****************************/
/* Close the socket and exit */
/*****************************/
rc = close(client_sock);
return 0;
}