Never too late to learn.

0%

Liunx Unix系统编程手册-SOCKET

Linux/UNIX系统编程手册

[德] Michael Kerrisk

第56章 SOCKET:介绍

SOCKET 套接字

socket是一种IPC方法,它允许位于同一主机或者使用网络连接起来的不同主机上的应用程序之间交换数据。

使用socket()系统调用来创建一个socket,它返回一个用来在后续系统调用中应用该socket的文件描述符。

fd = socket(domain, type, protocol)

现代操作系统至少支持以下domain
UNIX(AF_UNIX), IPv4(AF_INET), IPv6(AF_INET6)

domain 执行的通信 应用程序间的通信 地址格式 地址结构
AF_UNIX 内核中 同一主机 路径名 sockaddr_in
AF_INET IPv4 通过ipv4连接的主机 31位ipv4地址+16位端口号 sockaddr_in
AF_INET6 IPv6 通过ipv6连接的主机 128位ipv6地址+16位端口号 sockaddr_in6

每个socket实现都提供至少两种类型的sockets:流(stream)和数据报(datagram)

属性 数据报
可靠的传送
消息边界保留
面向连接

Stream sockets(SOCK_STREAM)提供了一个可靠的双向的字节流通讯通道, 使用传输控制协议(TCP)

  • 可靠的: 表示数据的传输会完整的得到传送或者收到传输失败的通知
  • 双向的: 表示两个socket之间的数据可以互相传输
  • 字节流: 表示与管道一样不存在消息边界的概念

Datagram sockets(SOCK_DGRAM)提供了不可靠无连接的面向消息的通道,允许数据以被称为数据报的消息的形式进行交换,使用用户数据报协议(UDP)。
在数据报socket中,消息边界得到了保留,但数据传输时不可靠的。消息的到达可能是无序的,重复的或者无法到达的。

创建一个socket: socket()

socket()系统调用创建一个新socket

1
2
3
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
Returns file descriptor on success, or –1 on error

domain指定socket的通信domain,type指定socket类型。
socket()在成功时返回一个引用在后续系统调用中会用到的新创建的socket的文件描述符。

将socket绑定到地址: bind()

bind()系统调用将一个socket绑定到一个地址上。

1
2
3
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
Returns 0 on success, or –1 on error

stream_socket用到的系统调用

stream_socket.jpg

监听接入连接:listen()

listen()系统调用将文件描述符sockfd引用的socket标记监听模式。

1
2
3
#include <sys/socket.h>
int listen(int sockfd, int backlog);
Returns 0 on success, or –1 on error

backlog参数限制挂起连接的数量,在accept()调用之前,可能有客户端的connect()过来,这些连接会被挂起。

接受连接: accept()

1
2
3
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
Returns file descriptor on success, or –1 on error

accept()会创建一个新socket,这个新socket会与执行connect()的socket进行连接。

连接远端socket:connet()

1
2
3
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
Returns 0 on success, or –1 on error

stream socket I/O

流socket上的I/O与管道上的I/O语义上一样,执行需要使用read()和write()系统调用。

datagram_socket用到的系统调用

datagram_socket.jpg

交换数据报: recvfrom() 和 sendto()

数据报socket()上使用recvfrom(),sendto()系统调用来接受和发送数据报。

1
2
3
4
5
6
7
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buffer, size_t length, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
Returns number of bytes received, 0 on EOF, or –1 on error
ssize_t sendto(int sockfd, const void *buffer, size_t length, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
Returns number of bytes sent, or –1 on error

关闭连接:close()

Coffee? ☕