linux进程间通信--套接字

2021-02-28

套接字(Socket)用于协调不同计算机上的进程间通信,也就是基于网络的通信。当然,也可以在本机上使用套接字进行进程间的通信。

套接字通信的方式非常多,有Unix域套接字、TCP套接字、UDP套接字、链路层套接字等等。

socket

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

int socket(int domain, int type, int protocol);

参数说明:

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)
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.
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

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函数

#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

  1. 函数用途

    • getsockname:获取与某个套接字关联的本地协议地址
    • getpeername:获取与某个套接字关联的外地协议地址
  2. 需要这两个函数的原因

    • 在一个没有调用bind的TCP客户上,connect成功后,getsockname用于获取由内核赋予该连接的本地IP地址和本地端口号;
    • 在以端口号0调用bind(告知内核去选择本地端口号)后,getsockname用于获取由内核赋予的本地端口号;
    • getsockname可以用于获取某个套接字的地址族 
      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
words: 1103 tags: linux c socket