UNIX domain sockets are used for communication between processes running on the same machine. Although Internet domain sockets can be used for the same purpose, UNIX domain sockets are more efficient. UNIX domain sockets only replicate data; they do not perform protocol processing, do not need to add or remove network headers, do not have to compute the test and, do not produce sequential numbers, do not have to send a confirmation message.
1. Non-named UNIX domain sockets
UNIX domain sockets are used to communicate between processes running on a single machine, providing both streaming and datagram interfaces. UNIX Domain Datagram services are reliable and do not lose messages or deliver errors.
A UNIX domain socket is a mixture of sockets and pipes.
To create a pair of unnamed, interconnected Unxi domain sockets, the user can use the Socketpair function.
#include <sys/types.h>
#include <sys/socket.h>
int socketpair (int d, int type, int protocol, int sv[ 2]);
The two descriptors created with Socketpair are equivalent (create a pair of the connected sockets, the two sockets are).
Creates a pair of anonymous connected Full-duplex sockets, and the two socket descriptors that are established are placed in sv[0] and sv[1].
Parameter introduction:
The 1th parameter d (domain), which represents the protocol family, can only be af_local or Af_unix;
The 2nd parameter type, representing the type, can only be 0.
The 3rd parameter protocol, which represents the protocol, can be Sock_stream or sock_dgram. The socket pair established with SOCK_STREAM is a pipe flow, and unlike the general pipe, the socket is bidirectional to the established channel, that is, each end can read and write. regardless of the data stream or datagram Protocol, UNIX domain sockets are reliable and do not lose packets.
The 4th parameter SV, which is used to save the established socket pairs.
(Why the man Sockepair prototype, but when used, the second and third arguments are reversed, only correctly.) ) Example:
#include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <string.h> #in
Clude <sys/types.h> #include <unistd.h> int main (void) {int i_fd_arr[2];
int i_pid;
Char psz_wbuf[16] = "0123456789";
Char psz_rbuf[16] = {0};
if (Socketpair (Af_unix, Sock_stream, 0, I_fd_arr) < 0) {perror ("Socketpair");
return-1;
} if ((I_pid = fork ()) < 0) {perror ("fork");
return-1;
else if (0 = i_pid) {//child close (i_fd_arr[0));
if (write (i_fd_arr[1), Psz_wbuf, strlen (psz_wbuf)) < 0) {perror ("write");
Exit (-1);
} memset (psz_rbuf, 0, sizeof (PSZ_RBUF));
if (read (i_fd_arr[1], psz_rbuf,) < 0) {perror ("read");
Exit (-1); } prinTF ("Child read:%s\n", psz_rbuf);
else {//parent close (i_fd_arr[1]);
if (read (i_fd_arr[0], psz_rbuf,) < 0) {perror ("read");
Exit (-1);
printf ("Parent read:%s\n", psz_rbuf);
memset (psz_wbuf, 0, sizeof (PSZ_WBUF));
strncpy (Psz_wbuf, "9876543210", sizeof (PSZ_WBUF)-1);
if (write (i_fd_arr[0), Psz_wbuf, strlen (psz_wbuf)) < 0) {perror ("write");
Exit (-1);
} return 0; }
Execution results:
yan@yan-vm:~$./a.out
Parent read:0123456789
Child read:9876543210 2. Name UNIX domain sockets
Although the Socketpair function creates a pair of sockets that are interconnected, each socket has no name. This means that unrelated processes cannot use them .
We can name the UNIX domain socket and use it for the notice service. Note, however, that theaddresses used by Unxi and sockets are different from Internet domain sockets.
UNIX domain sockets use addresses that are typically a file path in a file system (a set of interface files: the 4.3-section file type in Apue, which starts with s), is a special file that can only be used as a domain socket and cannot read and write:
is a file that starts with S.
The address of a UNIX domain socket is represented by the SOCKADDR_UN structure.
In linux2.4.22, the SOCKADDR_UN structure is defined in file <sys/un.h> in the following form.
struct sockaddr_un{
sa_family_t sun_family; Af_unix
Char sun_path[108]; Pathname
};
Sun_path members contain all the names, and when we bind an address to a UNIX domain socket, the system uses the pathname to create a s_ifsock file.
This file is used only to inform the client process of the socket name. The file cannot be opened, nor can it be used by the application for communication.
if the file already exists when we attempt to bind the address, the bind request fails. When the socket is closed, the file is not automatically deleted, so we must make sure that the file is unlinked before the application terminates.
The server process can use the standard bind, listen, and accept functions to schedule a unique UNIX domain connection for the client process. The client process connects to the server process using connect; After the server process accepts the connect request, a unique connection exists between the server process and the client process. This style is similar to the operation of Internet sockets. TCP Example:
Server.c
#include <stdio.h> #include <sys/socket.h> #include <sys/un.h> #include <string.h> #in
clude <unistd.h> int main (void) {int i_listenfd = 0, i_clientfd = 0;
struct Sockaddr_un addr_server, addr_client;
Char psz_path[32] = "./server_unixsocket_file";
int i_caddr_len = sizeof (struct sockaddr_un);
int i_saddr_len = sizeof (struct sockaddr_un);
Char psz_rbuf[32] = {0};
Char psz_wbuf[32] = "I am server.";
int i_readlen = 0;
Create a UNIX domain stream socket if (I_LISTENFD = socket (Af_unix, sock_stream, 0) < 0) {
Perror ("socket");
return-1;
//in case it already exists unlink (Psz_path);
Fill in socket address structure memset (&addr_server, 0, sizeof (addr_server));
addr_server.sun_family = Af_unix; strncpy (Addr_server.sun_path, Psz_path, sizeof (Addr_server.sun_path)-1 );
Bind the name to the descriptor if (Bind (I_LISTENFD, (struct sockaddr *) &addr_server, I_saddr_len) < 0)
{perror ("bind");
return-1;
} if (Listen (I_LISTENFD, < 0) {perror ("listen");
return-1;
while (1) {if (I_clientfd = Accept (I_LISTENFD, (struct sockaddr *) &addr_client,
(socklen_t *) &i_caddr_len)) < 0) {perror ("accept");
return-1;
printf ("Client is:%s\n", Addr_client.sun_path);
if ((I_readlen = Read (I_CLIENTFD, psz_rbuf, sizeof (PSZ_RBUF)-1)) < 0) {perror ("read");
return-1;
} Psz_rbuf[i_readlen] = ';
printf ("Receive msg:%s\n", psz_rbuf);
if (Write (I_CLIENTFD, Psz_wbuf, strlen (PSZ_WBUF) + 1) < 0) { Perror ("write");
return-1;
} unlink (Psz_path);
return 0; }
Client.c
#include <stdio.h> #include <sys/un.h> #include <sys/socket.h> #include <string.h> #in
clude <unistd.h> int main (void) {int i_fd = 0;
struct Sockaddr_un addr;
Char psz_path[32] = "./client_unixsocket_file";
Char serverpath[32] = "./server_unixsocket_file";
int i_addr_len = sizeof (struct sockaddr_un);
Char psz_wbuf[32] = "I am client.";
Char psz_rbuf[32] = {0};
int i_readlen = 0;
if ((I_FD = socket (Af_unix, sock_stream, 0)) < 0) {perror ("socket");
return-1;
} memset (&addr, 0, sizeof (addr));
addr.sun_family = Af_unix;
strncpy (Addr.sun_path, Psz_path, sizeof (Addr.sun_path)-1);
Unlink (Psz_path);
if (Bind (I_FD, (struct sockaddr *) &addr, I_addr_len) < 0) {perror ("bind");
return-1; }//fill socket adress structure with server ' s address
memset (&addr, 0, sizeof (addr));
addr.sun_family = Af_unix;
strncpy (Addr.sun_path, Serverpath, sizeof (Addr.sun_path)-1);
if (Connect (i_fd, (struct sockaddr *) &addr, I_addr_len) < 0) {perror ("connect");
return-1;
} if (Write (I_FD, Psz_wbuf, strlen (PSZ_WBUF) + 1) < 0) {perror ("write");
return-1; } if (I_readlen = Read (I_FD, psz_rbuf, sizeof (PSZ_RBUF)-1)) < 0 {perror ("writ
E ");
return-1;
} Psz_rbuf[i_readlen] = ';
printf ("Receive msg:%s\n", psz_rbuf);
Unlink (Psz_path);
return-1; }
the client does not have to bind, so the path is not set for the client. Without a path, the server output client is empty in the example.
Run server first, then run client. Run Result:
Service side:
yan@yan-vm:~/apue$./unixserver
Client is:./client_unixsocket_file
Receive msg:i AM client.
Client:
yan@yan-vm:~/apue$./unixclient
Receive MSG:I AM server.
UDP Example:
Server
#include <stdio.h> #include <sys/socket.h> #include <sys/un.h> #include <STRING.H&G
T
#include <unistd.h> int main (void) {int i_listenfd = 0/*, i_clientfd = 0*/;
struct Sockaddr_un addr_server, addr_client;
Char psz_path[32] = "./server_unixsocket_file";
int i_caddr_len = sizeof (struct sockaddr_un);
int i_saddr_len = 0;
Char psz_rbuf[32] = {0};
Char psz_wbuf[32] = "I am server.";
int i_readlen = 0;
Create a UNIX domain stream socket if (I_LISTENFD = socket (Af_unix, SOCK_DGRAM, 0) < 0) {
Perror ("socket");
return-1;
//in case it already exists unlink (Psz_path);
Fill in socket address structure memset (&addr_server, 0, sizeof (addr_server));
addr_server.sun_family = Af_unix; strncpy (Addr_server.sun_path, Psz_path, sizeof (Addr_server.sun_path)-1);
Bind the name to the descriptor I_saddr_len = strlen (addr_server.sun_path) + sizeof (addr_server.sun_family); if (Bind (I_LISTENFD, (struct sockaddr *) &addr_server, I_saddr_len) < 0) {perror ("Bi
nd ");
return-1;
while (1) {I_readlen = Recvfrom (I_LISTENFD, Psz_rbuf, sizeof (PSZ_RBUF)-1, 0,
(struct sockaddr *) &addr_client, (socklen_t *) &i_caddr_len);
if (I_readlen < 0) {perror ("read");
return-1;
printf ("Client is:%s\n", Addr_client.sun_path);
Psz_rbuf[i_readlen] = ' the ';
printf ("Receive msg:%s\n", psz_rbuf); if (SendTo (I_LISTENFD, Psz_wbuf, strlen (psz_wbuf) + 1, 0, (struct sockaddr *) &addr_client, i_caddr _len) < 0) {perror ("writE ");
return-1;
} unlink (Psz_path);
return 0; }
Client
#include <stdio.h> #include <sys/un.h> #include <sys/socket.h> #include <string.h> #in
clude <unistd.h> int main (void) {int i_fd = 0;
struct Sockaddr_un addr;
Char psz_clientpath[32] = "./client_unixsocket_file";
Char psz_serverpath[32] = "./server_unixsocket_file";
int i_addr_len = 0;
Char psz_wbuf[32] = "I am client.";
Char psz_rbuf[32] = {0};
int i_readlen = 0;
if ((I_FD = socket (Af_unix, SOCK_DGRAM, 0)) < 0) {perror ("socket");
return-1;
} memset (&addr, 0, sizeof (addr));
addr.sun_family = Af_unix;
strncpy (Addr.sun_path, Psz_clientpath, sizeof (Addr.sun_path)-1);
Unlink (Psz_clientpath);
I_addr_len = strlen (addr.sun_path) + sizeof (addr.sun_family);
if (Bind (I_FD, (struct sockaddr *) &addr, I_addr_len) < 0) {perror ("bind");
return-1;
}
Fill socket adress structure with server's address memset (&addr, 0, sizeof (addr));
addr.sun_family = Af_unix;
strncpy (Addr.sun_path, Psz_serverpath, sizeof (Addr.sun_path)-1);
I_addr_len = strlen (addr.sun_path) + sizeof (addr.sun_family);
if (SendTo (I_FD, Psz_wbuf, strlen (psz_wbuf) + 1, 0, (struct sockaddr *) &addr, I_addr_len) < 0)
{perror ("write");
return-1; if (I_readlen = Recvfrom (i_fd, Psz_rbuf, sizeof (PSZ_RBUF)-1, 0, (struct sockaddr *) &add
R, (socklen_t *) &i_addr_len)) < 0) {perror ("write");
return-1;
} Psz_rbuf[i_readlen] = ';
printf ("Receive msg:%s\n", psz_rbuf);
Unlink (Psz_clientpath);
return-1; }
After testing, in UDP, if the client does not bind an address, it can only send messages from the client to the server side, can not send messages to the client from the service side, will report the following error:
Write:transport endpoint is not connected
If the following error occurs: Invalid argument (22), then examine the parameters carefully, preferably with the same value as in the example.
Http://www.th7.cn/system/lin/201402/50519.shtml
http://blog.csdn.net/todd911/article/details/20285711
http://jishublog.iteye.com/blog/1945230