socket 基础篇

Socket作用

没有socket的网络通信是这样的


有了 socket 之后,是这样的:

可见,socket 为用户进程和 TCP/IP 协议簇通信中提供了中间的抽象层,也即接口。

Socket 的接口函数

在 TCP 中的client/server的网络通信中,流程大概如下图所示:

c/s

各函数的c接口及Python接口解释如下:

socket()

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

socket() creates an endpoint for communication and returns a file descriptor that refers to that endpoint.
其中的 file desciptor 简记为 sockfd.

  • domain: specifies a communication domain; 即协议域, 常见的有

    • AF_UNIX, AF_LOCAL: Local communication
    • AF_INET: IPv4 Internet protocols
    • AF_INET6: IPv6 Internet protocols
  • type: specifies the communication semantics. 常见的有

    • SOCK_STREAM: Provides sequenced, reliable, two-way, connection-
      based byte streams. 用于 TCP 传输
    • SOCK_DGRAM: Supports datagrams (connectionless, unreliable
      messages of a fixed maximum length). 用于 UDP 传输
    • SOCK_RAW: Provides raw network protocol access. 允许应用层直接发送和接受来自 IP 层的 package 而无需经过传输层。可用于 ICMP 和 IGMP 传输
  • protocol: 定协议,有IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP,分别对应于 TCP, UDP, SCTP 传输协议。如果指定为0,表示由内核根据type指定默认的通信协议

对应的python接口

socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)

bind()

 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

When a socket is created with socket(), it exists in a name space (address family) but has no address assigned to it. bind() assigns the address specified by addr to the socket referred to by the file descriptor sockfd. Traditionally, this operation is called “assigning a name to a socket”.

  • sockdf: 即为 socket() 的返回值。

  • addr: The actual structure passed for the addr argument will depend on the
    address family. 对应的 IPV4 为

struct sockaddr_in {
    sa_family_t    sin_family; /* address family: AF_INET */
    in_port_t      sin_port;   /* port in network byte order */
    struct in_addr sin_addr;   /* internet address */
};

/* Internet address. */
struct in_addr {
    uint32_t       s_addr;     /* address in network byte order */
};
  • addrlen: addrlen specifies the size, in bytes, of the address structure pointed to by addr.

!Note: 通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。

对应的 Python 接口

socket.bind(address)

AF_INET即 IPV4 对应的 address 为 (host, port).

listen()

int listen(int sockfd, int backlog);

listen for connections on a socket.

  • backlog: defines the maximum length to which the queue of pending connections for sockfd may grow.

!Note: 调用listen后,内核就会建立两个队列,一个SYN队列,表示接受到请求,但未完成三次握手的连接;另一个是ACCEPT队列,表示已经完成了三次握手的队列. backlog 已经完成三次握手而等待accept()的连接数

对应的 Python 接口

socket.listen([backlog])

connect()

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

The connect() system call connects the socket referred to by the file descriptor sockfd to the address specified by addr.

  • sockfd: 客户端的 sockfd

  • addr: 服务端的 socket 地址

对应的 Python 接口

socket.connect(address)

accept()

 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

accept a connection on a socket, It extracts the first connection request on the queue of pending connections for the listening socket, sockfd, creates a new connected socket, and returns a new file descriptor referring to that socket. The newly created socket is not in the listening state.

  • sockfd: The argument sockfd is a socket that has been created with socket(), bound to a local address with bind(), and is listening for connections after a listen().

  • addr: The argument addr is a pointer to a sockaddr structure. This structure is filled in with the address of the peer socket, as known to the communications layer.

!Note: If no pending connections are present on the queue, and the socket is
not marked as nonblocking, accept() blocks the caller until a
connection is present. If the socket is marked nonblocking and no
pending connections are present on the queue, accept() fails with the
error EAGAIN or EWOULDBLOCK.

  • EAGAIN 和 EWOULDBLOCK 同样东西
    #define EAGAIN 11 /* Try again /
    #define EWOULDBLOCK EAGAIN /
    Operation would block */
    当应用程序进行一些非阻塞(non-blocking)操作(对文件或socket)的时候。例如,以 O_NONBLOCK的标志打开文件/socket/FIFO,如果你连续做read操作而没有数据可读。此时程序不会阻塞起来等待数据准备就绪返 回,read函数会返回一个错误EAGAIN,提示你的应用程序现在没有数据可读请稍后再试。

对应 python 的接口

socket.accept()

The return value is a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection.

!Note: 监听套接字 v.s. 连接套接字

  • 监听套接字: 由服务端 socket() 函数返回 sockfd,并传入 listen() 方法里的 套接字.
  • 连接套接字: 在客户端 connect() 成功后,accept() 新创建的套接字.
  • 一个服务器通常通常仅仅只创建一个监听socket描述字,它在该服务器的生命周期内一直存在。内核为每个由服务器进程接受的客户连接创建了一个已连接socket描述字,当服务器完成了对某个客户的服务,相应的已连接socket描述字就被关闭。

read()/write()

close() v.s. shutdown()

参考

下图来自 Socket 编程实战

close

三次握手

简单的原理图

稍微复杂些的(来自曾志优同学):

733402-20160107184421450-856838651.png

步骤详见 socket原理详解的 3.6、listen、connect、accept流程及原理

更详细的原理请见 高性能网络编程(一)----accept建立连接

参考

socket 进阶篇

  • 理解并使用 select: I/O 多路复用
  • socketserver模块的使用和源码剖析, 参考 python之socket编程
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,589评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,615评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,933评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,976评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,999评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,775评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,474评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,359评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,854评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,007评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,146评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,826评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,484评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,029评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,153评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,420评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,107评论 2 356

推荐阅读更多精彩内容