Transcript UNIX Domain sockets
UNIX Domain sockets
The Linux Programming Interface (ch 57) UNIX Network Programming – Vol 1, 3ed (ch 15)
Using Sockets in UNIX domain
• Unnamed sockets – socketpair( ) – Does not bind to transport layer ports – Creates a pair of sockets that are connected – Typically used to communicate between related processes – Communications similar to pipe • Traditional sockets in UNIX – 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 2
socketpair( )
• int socketpair (int family, int type, int protocol, int sockfd[2]); – Family must be AF_LOCAL – Type may be SOCK_STREAM or SOCK_DGRAM – protocol must be 0 – On success, the pair of socket descriptors (sockfd) are connected together and available for communications • #include
3
sockpair.cpp
#define LB_SIZE 128 int main ( ) { time_t now; char child_buf[LB_SIZE], parent_buf[LB_SIZE]; pid_t pid; int sockfd[2], outSize, inSize; bool keepLooping; time (&now); keepLooping = true; cout << "Socket Pair test at " << ctime(&now);
socketpair (AF_LOCAL, SOCK_STREAM, 0, sockfd);
pid = fork() ; if (pid == 0) { // child process while (keepLooping) { inSize =
recv(sockfd[1], child_buf, LB_SIZE, 0);
child_buf[inSize] = '\0'; if (strncmp(child_buf, "bye", 3) == 0) keepLooping = false; cout << "Child received: " << child_buf << endl; } cout << "Closing child process" << endl; return 0; } //end of child process section 4
sockpair.cpp
} else if (pid > 0) { //parent process while (keepLooping) { cout << "Enter text to send to child: " << endl; cin.getline(parent_buf, LB_SIZE); outSize = strlen(parent_buf); if (strncmp(parent_buf, "bye", 3) == 0) keepLooping = false;
send (sockfd[0], parent_buf, outSize, 0);
} cout << "Closing parent process..." << endl; return 0; } 5
sockpair example output
rcotter@kc-sce-450p2 sockpair]$ ./sockpair Socket Pair test at Wed Oct 12 14:18:28 2011 Enter text to send to child: This is the first message Enter text to send to child: Child received: This is the first message This is the second message Enter text to send to child: Child received: This is the second message bye Closing parent process...
Child received: bye Closing child process [rcotter@kc-sce-450p2 sockpair]$ 6
Traditional UNIX Domain Sockets
• struct sockaddr_un { sa_family_t sun_family; //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( ); 7
UNIX Domain Sockets example
8
Traditional UNIX Domain Sockets
Server Socket mytemp.txt
Client Socket “unnamed” 9
UNIX Domain socket created by bind
10
unix_udp_echos.cpp
#include
unix_udp_echos.cpp
} sockfd = socket(
AF_LOCAL
, SOCK_DGRAM, 0); unlink(udp_path); bzero(&servaddr, sizeof(servaddr));
servaddr.sun_family = AF_LOCAL; strcpy(servaddr.sun_path, udp_path);
bind(sockfd, (sockaddr *) &servaddr, sizeof(servaddr)); UDP_echo(sockfd, (sockaddr *) &cliaddr, sizeof(cliaddr)); 12
unix_udp_echos.cpp
void UDP_echo(int sockfd, sockaddr *pcliaddr, socklen_t clilen) { int socklen_t len; n; char for ( ; ; ) { mesg[MAXLINE]; memset(&mesg, 0, MAXLINE); len = clilen;
n = recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);
cout << "We just got " << n << " char: " << mesg << endl;
sendto(sockfd, mesg, n, 0, pcliaddr, len);
} } 13
unix_udp_echo.cpp
#include
unix_udp_echo.cpp
} sockfd = socket(AF_LOCAL, SOCK_DGRAM, 0); bzero(&cliaddr, sizeof(cliaddr)); cliaddr.sun_family = AF_LOCAL; /* bind an address for us */ // Bind the client to a local (unique but unnamed) file
strcpy(cliaddr.sun_path, tmpnam(NULL)); bind(sockfd, (sockaddr *) &cliaddr, sizeof(cliaddr));
//Identify the server’s address (file) bzero(&servaddr, sizeof(servaddr)); /* fill in server's address */ servaddr.sun_family = AF_LOCAL;
strcpy(servaddr.sun_path, udp_path); UDPecho(sockfd, (sockaddr *) &servaddr, sizeof(servaddr));
close(sockfd); exit(0); 15
unix_udp_echo.cpp
void UDPecho(int sockfd, const sockaddr *pservaddr, socklen_t servlen) { int char n; sendline[MAXLINE], recvline[MAXLINE + 1]; while (cin.getline(sendline, MAXLINE) != NULL) { if (strncmp ("_bye", sendline, 4) == 0) break; sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen); n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL); recvline[n] = 0; /* null terminate */ cout << recvline << endl; } cout << "We jumped out of the loop" << endl; } 16
UNIX Domain Sockets example
17
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).
18