轉載自 原文地址 http://www.thomasstover.com/uds.html

轉載自 中文http://bbs.sjtu.edu.cn/bbstcon,board,GNULinux,reid,1345013026.html

"Unix Domain Sockets? - I've Heard of Those Before"

The often overlooked Unix domain socket facility is one of the most powerful features in any modern Unix. Most socket programing books for Unix discus the topic merely in an academic sense without ever explaining why it matters or what it is used for. Besides being the only way utilize certain abilities of the operating system, it is an area programers new to Linux, BSD, and other Unices definitely need to be aware of. This is not a tutorial on sockets, rather a review of the features and benefits of one area of sockets programming.

Background and Context

Unix domain sockets are sometimes called "local" sockets. This can be misleading as it implies that it has something to do with a loopback adapter. The closest thing to a Unix domain socket would be a pipe. Unix pipes are an integral cornerstone of the OS at large. Analogous to a water pipe with water flowing in one direction, a stream of bytes flows from the write side of a pipe to the read side. A separate open file descriptor maintains a reference to the read and write side of a pipe. The different sides of the pipe can be in different processes or threads as long as they reside on the same local computer. Let us review the distinguishing characteristics of pipes in Unix.
  • Writes less than 4kb are atomic
  • Pipes can be created and inherited across a fork() call, as well as shared between threads.
  • Pipes can also be given a name in the file system. These fifos (or named pipes) exist beyond the lives of processes. Two different processes can obtain a reference to the pipe with open() as opposed to having to inherit a file descriptor.
  • Writing to a pipe with a filled buffer results in a SIGSTOP signal.
  • Pipes are generally considered to be faster than Unix domain sockets.
  • Processes using pipes must still perform context switches with the kernel to use the read() and write() system calls.
As an exception to the fact that pipes must be written from one side and read from the other, Solaris pipes are full duplex. On Linux and BSD for example, full duplex operations with pipes use two different pipes. Named pipes and unnamed pipes are essentially the same thing with named pipes being created with mkfifo(), and unnamed ones with pipe().This is not the case with the Windows API. Windows provides two very different facilities, for what it calls named and anonymouspipes. Anonymous pipes are available in all versions of Windows, and behave much like Unix pipes. Besides being slower, there are several other variations such as an adjustable pipe cache size that also effects the threshold for atomic writes. Windows named pipes are roughly analogous to Unix domain sockets. They are only available on the NT derived Windows versions, and do not use the Windows networking socket interface, winsock, at all. Consequently, traditional socket multiplexing strategies such as select() can not be used with Windows named pipes as they can with unix domain sockets. They do have the advantage of reaching across multiple computers overServer Message Block (SMB).Update: It is also worth mentioning that OS/2 has a named pipe that, depending on what information you are reading, may or may not be able to communicate with Windows named pipes via SMB. Such SMB named pipes can also exist on *nix boxes machines runningSamba as part of facilities such as Winbind. Sadly, to my knowledge, there is no way to bridge a Unix domain socket with an SMB named pipe on a Unix environment using Samba without requiring adherence to the Samba project's license restrictions. Other conceivable avenues for such a bridge might involve Cygwin, or even socat.Update: Another worthwhile comparison to unix sockets is the Linux specific, netlink socket. Netlink sockets are used to comunicate between userspace and kernel space. For instance, to update routing or firewall information. It would be nice to find a good explanation of why another socket type was created instead of simply using unix sockets with perhaps abstract names (mentioned below).

On with It

A unix domain socket exists only inside a single computer. The word domain here has nothing to do with NIS, LDAP, or Windows, and instead refers to the file system. Unix domain sockets are identified by a file name in the file system like a named pipe would be. Programs communicating with a Unix domain socket must be on the same computer so they are not really a networking concept so much as they are an inter-process communication (IPC) concept. This explains why most networking books ignore them. They are interfaced with the same sockets API that is used for TCP/IP, UDP/IP, as well as other supported network protocols. You should be thinking at least two questions right now: "Why would a network program ever support Unix domain sockets as a transport?", and "Why would programs use a unix domain socket for an IPC mechanism instead of pipes, signals, or shared memory?". Here's some quick answers.
  • Unix domain sockets are secure in the network protocol sense of the word, because:

    • they cannot be eavesdropped on by a untrusted network
    • remote computers cannot connect to them without some sort of forwarding mechanism
  • They do not require a properly configured network, or even network support at all
  • They are full duplex
  • Many clients can be connect to the same server using the same named socket
  • Both connectionless (datagram), and connection oriented (stream) communication is supported
  • Unix domain sockets are secure in the IPC sense of the word, because:
    • File permissions can be configured on the socket to limit access to certain users or groups
    • Because everything that is going on takes place on the same computer controlled by a single kernel, the kernel knows everything about the socket and the parties on both sides. This means that server programs that need authentication can find out what user is connecting to them without having to obtain a user name and password.
  • Open file descriptors from one process can be sent to another totally unrelated process
  • Parties can know what PID is on the other side of a Unix domain Socket
  • The path name for a socket is limited to UNIX_PATH_MAX bytes long. On Linux, this is defined as 108 UNIX(7).
Not all of these features are available on every Unix. Worse there are variations on the way they are interfaced. Basic operations are pretty universally supported though. Let us move on to some examples.UPDATE: Many socket programs make use of the socketpair() function. This creates a matched pair of sockets without the usual, protocol specific, build up procedures. Typically this is used to create a socket to be for inter-thread communication, or communication with inherited processes. PF_UNIX is a valid choice for socketpair()'s domain parameter, allowing for another means to create a unix socket.

Basic Connection-Oriented Client & Server

We will start with a very basic client and a forking server. A forking server spawns a new process to handle each incoming connection. After a connection is closed, its handler process exits. This type of server frequently gets a bad reputation due to its poor performance as a web server. The reason it performs poorly as a web server is because with HTTP, every single request is made with its own connection.¹ The server thus spends a relatively disproportional amount of time creating and destroying processes versus actually handling requests. What is not commonly understood is that for other types of protocols which maintain a single connection during the entire time the client uses the server, a forking server is considered an acceptable design. Take Open SSH for example. The primary problem with this design for non-web server applications is that it is no longer as straightforward to share information between all the various handler instances. Multiplexing and multi-threaded as well as all sorts of other designs are out there, but the simple fork()ing server is a good as it gets for illustrating examples. Think of it as the "hello world" of server designs. Take the following sources.¹ UPDATE: While it is true that HTTP2's use of persistent connections does mitigate the above significantly, other aspects of why forking server designs might be choosen such as a 1:1 hanlder process to client user paradigm, are still not leveragable for HTTP.
client1.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <string.h>int main(void)
{struct sockaddr_un address;int  socket_fd, nbytes;char buffer[256];socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);if(socket_fd < 0){printf("socket() failed\n");return 1;}/* start with a clean address structure */memset(&address, 0, sizeof(struct sockaddr_un));address.sun_family = AF_UNIX;snprintf(address.sun_path, UNIX_PATH_MAX, "./demo_socket");if(connect(socket_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0){printf("connect() failed\n");return 1;}nbytes = snprintf(buffer, 256, "hello from a client");write(socket_fd, buffer, nbytes);nbytes = read(socket_fd, buffer, 256);buffer[nbytes] = 0;printf("MESSAGE FROM SERVER: %s\n", buffer);close(socket_fd);return 0;
}
server1.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
55
56
57
58
59
60
61
62
63
64
65
66
67
70
71
72
73
74
75
76
77
78
79
80
81
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>int connection_handler(int connection_fd)
{int nbytes;char buffer[256];nbytes = read(connection_fd, buffer, 256);buffer[nbytes] = 0;printf("MESSAGE FROM CLIENT: %s\n", buffer);nbytes = snprintf(buffer, 256, "hello from the server");write(connection_fd, buffer, nbytes);close(connection_fd);return 0;
}int main(void)
{struct sockaddr_un address;int socket_fd, connection_fd;socklen_t address_length;pid_t child;socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);if(socket_fd < 0){printf("socket() failed\n");return 1;} unlink("./demo_socket");/* start with a clean address structure */memset(&address, 0, sizeof(struct sockaddr_un));address.sun_family = AF_UNIX;snprintf(address.sun_path, UNIX_PATH_MAX, "./demo_socket");if(bind(socket_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0){printf("bind() failed\n");return 1;}if(listen(socket_fd, 5) != 0){printf("listen() failed\n");return 1;}while((connection_fd = accept(socket_fd, (struct sockaddr *) &address,&address_length)) > -1){child = fork();if(child == 0){/* now inside newly created connection handling process */return connection_handler(connection_fd);}/* still inside server process */close(connection_fd);}close(socket_fd);unlink("./demo_socket");return 0;
}

Armed with some basic knowledge of C, beginner level Unix system programing, beginner level sockets programing, how to lookup man pages, and Google, the above example will help you create a UDS client and server. To try it out open a couple terminal Windows, run the server in one, and the client in the other. After that try adding a something like sleep(15) to the server's connection handler, before it write()s back to the client. Bring up two more terminals, one with another instance of client and the other with top or ps -e, alsonetstat -ax. Experiment with that for a while. Learn anything?

At this point there are several things we could do with this technology, that is: the ability to have running programs communicate with other arbitrary programs on the same computer. Taking into consideration where in the file system our socket is created and with what permissions, this could allow programs running with different credentials, that started at different times, or even with different login sessions (controlling ttys) to exchange data. A common example of a program that works like this is syslogd. On many unix types, programs use a unix domain socket to pass log messages to the syslog server.

An Authenticated Server

Let us imagine a database server like PostgreSQL. The server can force every client program that connects to it to authenticate itself with a user name and password. It does this so that it can enforce its internal security policies based on what account a client is connecting with. Having to authenticate with a user name / password pair every time can get old so often other authentication schemes such as key pair authentication are used alternatively. In the case of local logins (client is on the same machine as the server) a feature of unix domain sockets known ascredentials passing can be used.

This is one area that is going to be different everywhere, so check your reference material. Let us look at how its done in Linux.

The Real Sockets IO API

Those new and old to sockets programming are often unaware that the sockets API actually has its own IO routines: send(), sendto(), sendmsg(),recv(), recvfrom(), and recvmsg(). These functions operate on sockets, not file descriptors. Unix automatically creates a file descriptor for a socket when its created (with the same integer value) so that IO operations can be performed on the socket just as with normal file descriptors, that is withread(), write(), and the like. This is why most of the time the underlying socket IO functions don't need to be used directly. Certain features do require the use of the lower level functions (like UDP). This is also why in Windows with winsock version 2 or greater (this is the version that internally uses the same open source BSD sockets code, unlike winsock 1) the same send/recv socket IO functions are available (all though not advertised). Also note that Windows too, provides a way to use sockets as Windows file HANDLES.

Linux uses a lower level socket function to grab the credentials of the process on the other side of unix domain socket, the multi-purposegetsockopt().

Credentials passing on Linux
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 struct ucred credentials;int ucred_length = sizeof(struct ucred);/* fill in the user data structure */if(getsockopt(connection_fd, SOL_SOCKET, SO_PEERCRED, &credentials, &ucred_length)){printf("could obtain credentials from unix domain socket");return 1;}/* the process ID of the process on the other side of the socket */credentials.pid;/* the effective UID of the process on the other side of the socket  */credentials.uid;/* the effective primary GID of the process on the other side of the socket */credentials.gid;/* To get supplemental groups, we will have to look them up in our accountdatabase, after a reverse lookup on the UID to get the account name.We can take this opportunity to check to see if this is a legit account.*/

File Descriptor Passing

File descriptors can be sent from one process to another by two means. One way is by inheritance, the other is by passing through a unix domain socket. There are three reasons I know of why one might do this. The first is that on platforms that don't have a credentials passing mechanism but do have a file descriptor passing mechanism, an authentication scheme based on file system privilege demonstration could be used instead. The second is if one process has file system privileges that the other does not. The third is scenarios where a server will hand a connection's file descriptor to another already started helper process of some kind. Again this area is different from OS to OS. On Linux this is done with a socket feature known as ancillary data.

It works by one side sending some data to the other (at least 1 byte) with attached ancillary data. Normally this facility is used for odd features of various underlying network protocols, such as TCP/IP's out of band data. This is accomplished with the lower level socket function sendmsg() that accepts both arrays of IO vectors and control data message objects as members of its struct msghdr parameter. Ancillary, also known as control, data in sockets takes the form of a struct cmsghdr. The members of this structure can mean different things based on what type of socket it is used with. Making it even more squirrelly is that most of these structures need to be modified with macros. Here are two example functions based on the ones available in Warren Gay's book mention at the end of this article. A socket's peer that read data sent to it by send_fd() without using recv_fd() would just get a single capital F.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 int send_fd(int socket, int fd_to_send){struct msghdr socket_message;struct iovec io_vector[1];struct cmsghdr *control_message = NULL;char message_buffer[1];/* storage space needed for an ancillary element with a paylod of length is CMSG_SPACE(sizeof(length)) */char ancillary_element_buffer[CMSG_SPACE(sizeof(int))];int available_ancillary_element_buffer_space;/* at least one vector of one byte must be sent */message_buffer[0] = 'F';io_vector[0].iov_base = message_buffer;io_vector[0].iov_len = 1;/* initialize socket message */memset(&socket_message, 0, sizeof(struct msghdr));socket_message.msg_iov = io_vector;socket_message.msg_iovlen = 1;/* provide space for the ancillary data */available_ancillary_element_buffer_space = CMSG_SPACE(sizeof(int));memset(ancillary_element_buffer, 0, available_ancillary_element_buffer_space);socket_message.msg_control = ancillary_element_buffer;socket_message.msg_controllen = available_ancillary_element_buffer_space;/* initialize a single ancillary data element for fd passing */control_message = CMSG_FIRSTHDR(&socket_message);control_message->cmsg_level = SOL_SOCKET;control_message->cmsg_type = SCM_RIGHTS;control_message->cmsg_len = CMSG_LEN(sizeof(int));*((int *) CMSG_DATA(control_message)) = fd_to_send;return sendmsg(socket, &socket_message, 0);}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 int recv_fd(int socket){int sent_fd, available_ancillary_element_buffer_space;struct msghdr socket_message;struct iovec io_vector[1];struct cmsghdr *control_message = NULL;char message_buffer[1];char ancillary_element_buffer[CMSG_SPACE(sizeof(int))];/* start clean */memset(&socket_message, 0, sizeof(struct msghdr));memset(ancillary_element_buffer, 0, CMSG_SPACE(sizeof(int)));/* setup a place to fill in message contents */io_vector[0].iov_base = message_buffer;io_vector[0].iov_len = 1;socket_message.msg_iov = io_vector;socket_message.msg_iovlen = 1;/* provide space for the ancillary data */socket_message.msg_control = ancillary_element_buffer;socket_message.msg_controllen = CMSG_SPACE(sizeof(int));if(recvmsg(socket, &socket_message, MSG_CMSG_CLOEXEC) < 0)return -1;if(message_buffer[0] != 'F'){/* this did not originate from the above function */return -1;}if((socket_message.msg_flags & MSG_CTRUNC) == MSG_CTRUNC){/* we did not provide enough space for the ancillary element array */return -1;}/* iterate ancillary elements */for(control_message = CMSG_FIRSTHDR(&socket_message);control_message != NULL;control_message = CMSG_NXTHDR(&socket_message, control_message)){if( (control_message->cmsg_level == SOL_SOCKET) &&(control_message->cmsg_type == SCM_RIGHTS) ){sent_fd = *((int *) CMSG_DATA(control_message));return sent_fd;}}return -1;}

Datagram Unix Domain Sockets

Most of the time programs that communicate over a network work with stream, or connection oriented technology. This is when an additional software layer such as TCP's Nagle algorithm creates a virtual communication circuit out of the many single atomic (stateless) packets used by a underlying packet switched network. Sometimes we want to instead simply work with individual packets, such is the case with UDP. This technology is often called datagram communication. This strategy allows for a variety of trade-offs. One is the ability to make a low overhead, high performance server with a single context or "main loop" that handles multiple simultaneous clients. Although unix domain sockets are not a network protocol they do utilize the sockets network interface, and as such also provide datagram features.

Datagram communication works best with an application that can put a complete atomic message of some sort in a single packet. This can be a problem for UDP as various setbacks can limit the size of a packet to as little as 512 bytes. The limit for datagrams over a unix domain socket is much higher. A complete example is beyond our scope for this article. Those interested should find a UDP example (much easier to find) and combine that with the techniques above. Update: A practical example on this site that does use datagram unix sockets is the PLC data proxy server, dndataserver, from the LAD Tools project. Designing servers this way can be a decent strategy to allow multiple processes to simultaniously share a resource (in this case PLC serial network access), without as much complexity as a connection oriented server. Let us review some of the considerations with datagram unix sockets, before we examine some example code.

  • If we want want messages (datagrams) from the server to be able to be sent back to the client, then the client will also need to bind to an address.
  • The server has to use a sockaddr structure to hold some reference to the client's return address.
server2.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
55
56
57
58
59
60
61
62
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>int main(void)
{int socket_fd;struct sockaddr_un server_address; struct sockaddr_un client_address; int bytes_received, bytes_sent, address_length;int integer_buffer;socklen_t address_length = sizeof(struct sockaddr_un);if((socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0){perror("server: socket");return 1;}memset(&server_address, 0, sizeof(server_address));server_address.sun_family = AF_UNIX;strcpy(server_address.sun_path, "./UDSDGSRV");unlink("./UDSDGSRV");       if(bind(socket_fd, (const struct sockaddr *) &server_address, sizeof(server_address)) < 0){close(socket_fd);perror("server: bind");return 1;}while(1){/* address_length is the length of the client's socket address structure.Hear this should always be the same since these socets are of type struct sockaddr_un. However, code that could be used with different types of sockets, ie UDS and UPD shouldtake care to hold and pass the correct value back to sendto on reply.  */bytes_received = recvfrom(socket_fd, (char *) &integer_buffer, sizeof(int), 0, (struct sockaddr *) &(client_address),&address_length);if(bytes_received != sizeof(int)){printf("datagram was the wrong size.\n");} else {integer_buffer += 5;bytes_sent = sendto(socket_fd, (char *) &integer_buffer, sizeof(int), 0,(struct sockaddr *) &(client_address), &address_length));}}unlink("./UDSDGSRV");close(socket_fd);return 0;
}
client2.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
55
56
57
58
59
60
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>int main(void)
{int socket_fd;struct sockaddr_un server_address; struct sockaddr_un client_address; int bytes_received, bytes_sent, address_length, integer_buffer;socklen_t address_length;if((socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0){perror("client: socket");return 1;}memset(&client_address, 0, sizeof(struct sockaddr_un));client_address.sun_family = AF_UNIX;strcpy(client_address.sun_path, "./UDSDGCLNT");unlink("./UDSDGCLNT");if(bind(socket_fd, (const struct sockaddr *) &client_address, sizeof(struct sockaddr_un)) < 0){perror("client: bind");return 1;}memset(&server_address, 0, sizeof(struct sockaddr_un));server_address.sun_family = AF_UNIX;strcpy(server_address.sun_path, "./UDSDGSRV");integer_buffer = 5;bytes_sent = sendto(socket_fd, (char *) &integer_buffer, sizeof(int), 0,(struct sockaddr *) &server_address, sizeof(struct sockaddr_un));address_length = sizeof(struct sockaddr_un);bytes_received = recvfrom(socket_fd, (char *) &integer_buffer, sizeof(int), 0, (struct sockaddr *) &(server_address),&address_length);close(socket_fd);if(bytes_received != sizeof(int)){printf("wrong size datagram\n");return 1;}printf("%d\n", integer_buffer);return 0;
}

Update: Broadcast Datagrams

The other main reason datagrams are used in network programming is in broadcast and multicast tasks. Unfortunately, there is no broadcast mechanism in Unix domain sockets. Unix provides the killpg() call for sending a signal to all members of a process group. This can be used to implement a broadcast facility of sorts, potentially in conjunction with shared memory. Linux specifically, also has the futex() call which also has the ability signal more than one process. On Windows, take a look at themail slots IPC facility.

Abstract Names

Another Linux specific feature is abstract names for unix domain sockets. Abstract named sockets are identical to regular UDS except that their name does not exist in the file system. This means two things: file permissions do not apply, and they can be accessed from inside chroot() jails. The trick is to make the first byte of the address name null. Look at the output from netstat -au to see what it looks while one of these abstract named sockets is in use. Example:

setting the first byte to null
1
2
3
4
5
6
 address.sun_family = AF_UNIX;snprintf(address.sun_path, UNIX_PATH_MAX, "#demo_socket");address.sun_path[0] = 0;bind(socket_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un));

Conclusion

Even if you never need to directly program UD sockets, they are an important facet of understanding both the Unix security model and the inter-workings of the operating system. For those that do use them, they open up a world of possibilities.

Unix Domain Sockets相关推荐

  1. php调用go服务问题,PHP 调用 Go 服务的正确方式 - Unix Domain Sockets

    问题 可能是由于经验太少,工作中经常会遇到问题,探究和解决问题的过程总想记录一下,所以我写博客经常是问题驱动,首先介绍一下今天要解决的问题: 服务耦合 我们在开发过程中可能会遇到这样的情况: 进程依赖 ...

  2. php与go服务之间调用,PHP调用Go服务的正确方式 - Unix Domain Sockets

    原标题:PHP调用Go服务的正确方式 - Unix Domain Sockets 作者:枕边书 链接:http://www.cnblogs.com/zhenbianshu/p/7265415.html ...

  3. 【Hadoop】the short-cricuit local reads feature cannnot be use because UNIX Domain sockets are not ava

    1.背景 报错 [Flink]UnsatisfieldlinkError : org.apache.hadoop.util.NativeCrc32 的时候,在上面还有一个warn. the short ...

  4. 网络协议之:socket协议详解之Unix domain Socket

    文章目录 简介 什么是Unix domain Socket 使用socat来创建Unix Domain Sockets 使用ss命令来查看Unix domain Socket 使用nc连接到Unix ...

  5. 网络协议之socket协议详解之Unix domain Socket

    简介 之前的文章我们讲到了Socket中的Stream Socket和Datagram Socket,和有连接的Stream Socket不同,Datagram Socket是无连接的.有连接的Str ...

  6. Unix Domain Socket

    unix域socket绑定地址时,需要指定一个文件路径,存在两种情况: (1)socket自动创建一个bind指定的文件路径对应的文件 (2)不需要创建socket文件,只需要命名一个全局名字即可让客 ...

  7. Unix domain socket IPC

    UNIX Domain socket 虽然网络socket也可用于同一台主机的进程间通讯(通过lo地址127.0.0.1),但是unix domain socket用于IPC更有效率:不需要经过网络协 ...

  8. 【socket】 unix域套接字(socketpair )通信|socketpair和pipe的区别|进程间通信-Unix domain socket

    目录 unix域套接字(socketpair )通信|socketpair和pipe的区别 socketpair机制 描述 原理 socketpair和pipe的区别 进程间通信-Unix domai ...

  9. Unix Domain Socket 域套接字实现

    主要注意流程: STREAM SOCKET: Server :  socket() --->  bind() ---> listen()  ---> accept() Client: ...

最新文章

  1. linux 修改图片的尺寸
  2. 补天白帽大会:无处不在的无线电攻击
  3. 通过容器编排和服务网格来改进Java微服务的可测性
  4. windows 版 arm-elf-gcc(转)
  5. 用UI讲故事,表达情感和创造个性
  6. 用户画像|产品经理应该如何定位用户
  7. 如何linux网页修改回80端口,linux下如何修改iptables开启80端口
  8. windows下创建目录函数_mkdir
  9. Subversion 服务配置安装手记(一)
  10. 对第三组博客的检查情况
  11. unity 3D入门
  12. windows黑客编程系列(一):运行单一实例
  13. 黑盒测试用例设计方法
  14. Jeesite框架IDEA导入,部署,启动,打包
  15. System x 服务器制作ServerGuide U盘安装Windows Server 2012 R2操作系统
  16. 【管理经验】管理的本质-激发善意
  17. mysql上机心得体会_数据库原理上机心得体会
  18. if(男深圳集体户口女非深圳户口)深圳准生证办理材料及流程
  19. 基于属性的测试,hypothesis以及查找bug
  20. Python数据可视化——图型参数介绍

热门文章

  1. 雨林木风发布 Windows一键还原 2011 v1.5.5.6
  2. 百度地图坐标转成腾讯地图坐标
  3. 多元相关性分析_数据分析的方法(三)
  4. 机器学习——不可逆矩阵处理
  5. kotlin java 知乎_GitHub - luciferldy/ZhihuDailyKotlin: 这是是一个使用 Kotlin 开发的知乎日报客户端...
  6. 国外计算机课程lab,计算机系统实验之bomblab
  7. 屏蔽google adsense和百度推广的广告
  8. 如何区分共射极放大电路与共基极放大电路?
  9. 校招|我的秋招记录——(自然语言处理-面经+感悟)
  10. dgraph的使用总结--------docker安装使用