linux进程间通信--套接字
2021-02-28
套接字(Socket)用于协调不同计算机上的进程间通信,也就是基于网络的通信。当然,也可以在本机上使用套接字进行进程间的通信。
套接字通信的方式非常多,有Unix域套接字、TCP套接字、UDP套接字、链路层套接字等等。
socket
1
2
3
4
| #include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
|
参数说明:
1
2
3
4
5
6
7
8
9
10
11
| Name Purpose Man page
AF_UNIX, AF_LOCAL Local communication unix(7)
AF_INET IPv4 Internet protocols ip(7)
AF_INET6 IPv6 Internet protocols ipv6(7)
AF_IPX IPX - Novell protocols
AF_NETLINK Kernel user interface device netlink(7)
AF_X25 ITU-T X.25 / ISO-8208 protocol x25(7)
AF_AX25 Amateur radio AX.25 protocol
AF_ATMPVC Access to raw ATM PVCs
AF_APPLETALK Appletalk ddp(7)
AF_PACKET Low level packet interface packet(7)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| The socket has the indicated type, which specifies the communication semantics. Currently defined types are:
SOCK_STREAM Provides sequenced, reliable, two-way, connection-based byte streams. An out-of-band data transmission mechanism may be supported.
SOCK_DGRAM Supports datagrams (connectionless, unreliable messages of a fixed maximum length).
SOCK_SEQPACKET Provides a sequenced, reliable, two-way connection-based data transmission path for datagrams of fixed maximum length; a consumer is required to read an entire packet with each input system call.
SOCK_RAW Provides raw network protocol access.
SOCK_RDM Provides a reliable datagram layer that does not guarantee ordering.
SOCK_PACKET Obsolete and should not be used in new programs; see packet(7).
Some socket types may not be implemented by all protocol families; for example, SOCK_SEQPACKET is not implemented for AF_INET.
Since Linux 2.6.27, the type argument serves a second purpose: in addition to specifying a socket type, it may include the bitwise OR of any of the following values, to modify the behavior of socket():
SOCK_NONBLOCK Set the O_NONBLOCK file status flag on the new open file description. Using this flag saves extra calls to fcntl(2) to achieve the same result.
SOCK_CLOEXEC Set the close-on-exec (FD_CLOEXEC) flag on the new file descriptor. See the description of the O_CLOEXEC flag in open(2) for reasons why this may be useful.
|
1
2
| protocol(最后一个参数)为0时,会自动选择type类型对应的默认协议。
IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC
|
return value
On success, a file descriptor for the new socket is returned. On error, -1 is returned, and errno is set appropriately.
error number
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| EACCES Permission to create a socket of the specified type and/or protocol is denied.
EAFNOSUPPORT
The implementation does not support the specified address family.
EINVAL Unknown protocol, or protocol family not available.
EINVAL Invalid flags in type.
EMFILE Process file table overflow.
ENFILE The system limit on the total number of open files has been reached.
ENOBUFS or ENOMEM
Insufficient memory is available. The socket cannot be created until sufficient resources are freed.
EPROTONOSUPPORT
The protocol type or the specified protocol is not supported within this domain.
Other errors may be generated by the underlying protocol modules.
|
INADDR_ANY: 0.0.0.0
getsockname和getpeername函数
1
2
3
| #include <sys/socket.h>
int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlrn);
int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);
|
返回:成功返回0,出错则为-1
函数用途
- getsockname:获取与某个套接字关联的本地协议地址
- getpeername:获取与某个套接字关联的外地协议地址
需要这两个函数的原因
- 在一个没有调用bind的TCP客户上,connect成功后,getsockname用于获取由内核赋予该连接的本地IP地址和本地端口号;
- 在以端口号0调用bind(告知内核去选择本地端口号)后,getsockname用于获取由内核赋予的本地端口号;
- getsockname可以用于获取某个套接字的地址族
1
2
3
4
5
6
7
8
9
10
| int sockfd_to_family(int sockfd) {
struct sockaddr_storage ss;
socklen_t len;
len = sizeof(ss);
if (getsockname(sockfd, (SA *) &ss , &len) < 0) {
return (-1);
}
return (ss.ss_family);
}
|
- 在一个以通配IP地址调用bind的TCP服务器上,与某个客户的连接一旦建立(accept成功返回),getsockname就可以用于获取由内核赋予该连接的本地IP地址;在这样的调用中,套接字描述符参数必须是已连接套接字的描述符,而不是监听套接字描述符;
- 当一个服务器 由调用过accept的某个进程通过调用exec来执行程序时,它能够获取客户身份的唯一途径是调用getpeername