UNIX Domain sockets

advertisement
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 <sys/sockets>
• Return zero on success, -1 on fail
• In Linux, sockets are full duplex (can both read and write),
however, POSIX standard does not require full duplex.
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 <iostream>, <fstream>, <sys/socket.h>, <sys/types.h>
#include <sys/un.h>, <string.h>, <unistd.h>
using namespace std;
#define MAXLINE 108
void UDP_echo(int sockfd, sockaddr *pcliaddr, socklen_t clilen);
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_un servaddr, cliaddr;
char udp_path[MAXLINE];
if (argc != 2)
{
cout << "Usage: " << argv[0] << " socket_address " << endl;
return(1);
}
if (strlen(argv[1]) < MAXLINE)
strcpy(udp_path, argv[1]);
else {
cout << "Socket Path name too long. Try again." << endl;
return(1);
}
11
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
n;
socklen_t len;
char
mesg[MAXLINE];
for ( ; ; ) {
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 <iostream>, <fstream>, <stdio.h>, <stdlib.h>, <sys/socket.h>
#include <sys/types.h>, <sys/un.h>, <string.h>, <unistd.h>
using namespace std;
#define MAXLINE 128
void UDPecho(int sockfd, const sockaddr *pservaddr, socklen_t servlen);
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_un cliaddr, servaddr;
char udp_path[MAXLINE];
if (argc != 2)
{
cout << "Usage: " << argv[0] << " socket_address " << endl;
return(1);
}
if (strlen(argv[1]) < MAXLINE)
strcpy(udp_path, argv[1]);
else {
cout << "Socket Path name too long. Try again." << endl;
return(1);
}
14
unix_udp_echo.cpp
sockfd = socket(AF_LOCAL, SOCK_DGRAM, 0);
bzero(&cliaddr, sizeof(cliaddr));
/* bind an address for us */
cliaddr.sun_family = AF_LOCAL;
// 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
n;
char
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
Download