200 likes | 215 Views
Learn about Unix domain sockets, bidirectional communication, socket functions, and creating TCP servers and clients.
E N D
UNIX Domain sockets The Linux Programming Interface (ch 57) UNIX Network Programming – Vol 1, 3ed (ch 15)
What is Unix (domain) Socket? • Socket: a bidirectional communication end-point • Berkeley socket: sockets used for data communication over Internet • Unix socket: sockets used for data communication between processes on the same Unix system. • It supports transmission of a reliable stream of bytes (SOCK_STREAM) as well as unreliable transmission of datagrams (SOCK_DGRAM)
What is Unix (domain) Socket? (cont) • The API for Unix domain sockets is similar to that of an Internet socket • But DO NOT use a underlying network protocol (TCP/IP) • all communication between processes occurs entirely within the operating system kernel. • Unix domain sockets use the file system as their address name space • Like FIFO (named pipe), but use functions like socket(), bind(), recv(), send(), accept(), instead of open(), write() • Sockaddr structure is different compare with berkeley socket, such as sockaddr_in(6)
What is Unix (domain) Socket? (cont) • Traditional Unix sockets • Binds to transport layer ports • Allows independent processes to communicate • Creates a file type object (socket) • Any process that can access the socket can use it. • Does not use network (IP) layer
UNIX Domain Sockets • struct sockaddr_un { sa_family_t sun_family; //AF_UNIX or AF_LOCAL char sunpath[108]; //NULL terminated path }; • sunpath length is 108 in Linux, but can be 104, 92 in other UNIX based systems. • File (path name) must not exist (be linked) prior to bind( ); • Unlink it If it exits • Note: AF_UNIX is portable by most system
Create a Unix TCP Server • Call socket() • Call bind() • Call listen() • Call accept() • Send/recv()
Create a Unix TCP client • Call socket() • Make a server sockaddr_un and call connect() • Send/recv()
Unix TCP Server Example • //headers • // echoserver.c • #include <stdio.h> • #include <stdlib.h> • #include <errno.h> • #include <string.h> • #include <sys/types.h> • #include <sys/socket.h> • #include <sys/un.h>
Unix TCP Server Example #define SOCK_PATH "myunixsockpath" int main(void){ int localsocket, newsocketfd, t, len; struct sockaddr_un local, client; char str[100]; if ((localsocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } local.sun_family = AF_UNIX; strcpy(local.sun_path, SOCK_PATH); unlink(local.sun_path); len = strlen(local.sun_path) + sizeof(local.sun_family); if (bind(localsocket, (struct sockaddr *)&local, len) == -1) { perror("bind"); exit(1); } if (listen(localsocket, 5) == -1) { perror("listen"); exit(1); }
Unix TCP Server Example while(1) { int done, n; printf("Waiting for a connection...\n"); t = sizeof(client); if ((newsocketfd = accept(localsocket, (struct sockaddr *)&client, &t)) == -1) { perror("accept"); exit(1); } printf("Connected.\n"); done = 0; do { n = recv(newsocketfd, str, 100, 0); if (send(newsocketfd, str, n, 0) < 0) { perror("send"); done = 1; } } while (!done); close(newsocketfd); } return 0; }
Run Unix TCP server $ gcc -o echoserver echoserver.c $ ./echoserver Waiting for a connection...
Unix TCP Client Example • //headers • // echoclient.c • #include <stdio.h> • #include <stdlib.h> • #include <errno.h> • #include <string.h> • #include <sys/types.h> • #include <sys/socket.h> • #include <sys/un.h>
Unix TCP Client Example #define SOCK_PATH "myunixsockpath” int main(void){ int localsocket, t, len; struct sockaddr_un server_info; char str[100]; if ((localsocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } printf("Trying to connect...\n"); server_info.sun_family = AF_UNIX; strcpy(server_info.sun_path, SOCK_PATH); len = strlen(server_info.sun_path) + sizeof(server_info.sun_family); if (connect(localsocket, (struct sockaddr *)&server_info, len) == -1) { perror("connect"); exit(1); } printf("Connected.\n");
Unix TCP Client Example while(printf(":> "), fgets(str, 100, stdin), !feof(stdin)) { if (send(localsocket, str, strlen(str), 0)== -1) { perror("send"); exit(1); } if ((t=recv(localsocket, str, 100, 0)) > 0) { str[t] = '\0'; printf("echo-from-server:> %s", str); } else { if (t < 0) perror("recv"); else printf("Server closed connection\n"); exit(1); } } close(localsocket); return 0; }
Run Unix TCP Client $ gcc -o echoclient echoclient.c $ ./echoclient Trying to connect ...Connected. :> hello echo-from-server:> hello :> This is client echo-from-server:> This is client :> $ ./echoserver Waiting for a connection... Connected.
Socketpair() • Pipe in Unix: unidirectional • CMD1 | CMD2 | CMD3 • cat filename | grep keyword | grep another keyword • socketpair( ): • Does not bind to transport layer ports • Creates a pair of unamed sockets that are connected • Typically used to communicate between related processes • Communications similar to pipe, but its bidirectional communication instead of undirection • No need to call listen, accept and connect functions
socketpair( ) • intsocketpair (int family, int type, int protocol, intsockfd[2]); • Family = AF_UNIX (AF_LOCAL works for most of systems as well) • Type may be SOCK_STREAM (TCP) or SOCK_DGRAM (UDP) • protocol must be 0 • On success, the pair of socket descriptors (sockfd) are connected together and available for communications #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> • Return zero on success, -1 on fail
sockpair.cpp int main(void){ int socketPairs[2]; /* the pair of socket descriptors */ char buf; /* for data exchange between processes */ int t; if (socketpair(AF_UNIX, SOCK_STREAM, 0, socketPairs) == -1) { perror("socketpair"); exit(1); } if (!fork()) { /* child */ recv(socketPairs[1], &buf, 1, 0); printf("child: read '%c'\n", buf); buf = toupper(buf); /* make it uppercase */ send(socketPairs[1], &buf, 1, 0); printf("child: sent '%c'\n", buf); } else { /* parent */ send(socketPairs[0], "b", 1, 0); printf("parent: sent 'b'\n"); recv(socketPairs[0], &buf, 1,0); printf("parent: read '%c'\n", buf); wait(NULL); /* wait for child to die */ } return 0;}
sockpair.cpp $ gcc -o socketpair socketpair.c $ ./socketpair parent: sent 'b’ child: read 'b’ child: sent 'B’ parent: read 'B'
Summary • socketpair( ) • Used to communicate between related processes. • Works like a full-duplex pipe (called a stream pipe) • Does not rely on transport layer functionality • UNIX Domain Sockets • Used to communicate between UNIX / Linux processes that have shared access to a socket file. • Can use file permissions to control access. • Uses transport layer (TCP or UDP), but not network layer (IP) • Removes IP / Ethernet packet size limitations (but still have transport layer limitations).