linux一切皆文件之tcp socket描述符(三)

一、知识准备

1、在linux中,一切皆为文件,所有不同种类的类型都被抽象成文件(比如:块设备,socket套接字,pipe队列)
2、操作这些不同的类型就像操作文件一样,比如增删改查等


二、环境准备

组件 版本
OS CentOS Linux release 7.5.1804


三、tcp socket 文件描述符

● 当我们建立一条TCP连接时,在linux操作系统中会创建一个socket文件描述符
● 通过文件描述符就能找到socket的几本信息,比如TCP四元组(client-ip:client-port --> server-ip:server-port

先准备2个脚本:
server.py主要用于建立客户端的连接请求,并且接收客户端传来的数据,然后将收到的数据回传给客户端
client.py每隔1秒向服务端发送一次'hello world'

server.py

import socket

server_addr = ('127.0.0.1' , 22222)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(server_addr)
sock.listen(5)

while True:
    conn, clientAddr = sock.accept()
    while True:
        data = conn.recv(100)
        conn.sendall(data)
        
sock.close()

client.py

import socket
import time

server_addr = ('127.0.0.1' , 22222)

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(server_addr)

while True:
    message = 'hello world!'
    sock.send(message)
    sock.recv(100)
    time.sleep(1)

sock.close()


分别启动server.py与client.py

[root@localhost ~]# python /tmp/server.py  &
[1] 14199
[root@localhost ~]# python /tmp/client.py  &
[2] 14202

查看server.py打开的文件描述符

[root@localhost ~]# ls -l /proc/14199/fd
total 0
lrwx------ 1 root root 64 Nov  7 07:42 0 -> /dev/pts/0
lrwx------ 1 root root 64 Nov  7 07:42 1 -> /dev/pts/0
lrwx------ 1 root root 64 Nov  7 07:42 2 -> /dev/pts/0
lrwx------ 1 root root 64 Nov  7 07:42 3 -> socket:[99154]
lrwx------ 1 root root 64 Nov  7 07:42 4 -> socket:[99155]
[root@localhost ~]# lsof -n | grep -E '99154|99155'
python    14199         root    3u     IPv4              99154       0t0        TCP 127.0.0.1:22222 (LISTEN)
python    14199         root    4u     IPv4              99155       0t0        TCP 127.0.0.1:22222->127.0.0.1:56946 (ESTABLISHED)

我们主要关注ESTABLISHED状态的socket描述符,也就是4 -> socket:[99155]

[root@localhost fd]# more /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
  ...
   4: 0100007F:56CE 0100007F:DE72 01 00000000:00000000 00:00000000 00000000     0        0 99155 1 ffff90d8bb0145c0 20 4 31 10 -1

进程打开了tcp socket 描述符4 -> socket:[99155],socket描述符指向内存中的socket结构体,该结构体详细描述了这个socket的详细信息

最重要的是TCP四元组(local_ip:local_port --> remote_ip:remote_port),拆分转换成10进制

0100007F:56CE

[root@localhost ~]# ((d=0x01))
[root@localhost ~]# ((c=0x00))
[root@localhost ~]# ((b=0x00))
[root@localhost ~]# ((a=0x7F))
[root@localhost ~]# ((e=0x56CE))
[root@localhost ~]# echo "$a.$b.$c.$d:$e"
127.0.0.1:22222

0100007F:DE72

[root@localhost ~]# ((d=0x01))
[root@localhost ~]# ((c=0x00))
[root@localhost ~]# ((b=0x00))
[root@localhost ~]# ((a=0x7F))
[root@localhost ~]# ((e=0xDE72))
[root@localhost ~]# echo "$a.$b.$c.$d:$e"
127.0.0.1:56946

在/proc/net/tcp包含了tcp连接的重要状态信息:
00000000:00000000 : 发送队列与接收队列 (正数第四个字段)
-1 : 慢启动门限 (倒数第一个字段)
10 : 拥塞窗口 (倒数第二个字段)

这里面还有很多描述:比如慢启动门限、传输队列以及接收队列、窗口探查等TCP相关的重要参数都可以查询到,具体的大家可以去看下《TCP/IP详解卷》

client.py也存在同样的行为:

[root@localhost ~]# ls -l /proc/14202/fd
total 0
lrwx------ 1 root root 64 Nov 19 04:43 0 -> /dev/pts/0
lrwx------ 1 root root 64 Nov 19 04:43 1 -> /dev/pts/0
lrwx------ 1 root root 64 Nov 19 04:43 2 -> /dev/pts/0
lrwx------ 1 root root 64 Nov 19 04:43 3 -> socket:[28728]
[root@localhost ~]# lsof -n | grep 28728
python    14202         root    3u     IPv4              28728       0t0        TCP 127.0.0.1:56946->127.0.0.1:22222 (ESTABLISHED)
[root@localhost fd]# more /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
  ...
3: 0100007F:C31A 0100007F:DE72 01 00000000:00000000 00:00000000 00000000     0        0 28728 3 ffff8a74ba1a0f80 20 4 30 10 -1

0100007F:56CE

[root@localhost ~]# ((d=0x01))
[root@localhost ~]# ((c=0x00))
[root@localhost ~]# ((b=0x00))
[root@localhost ~]# ((a=0x7F))
[root@localhost ~]# ((e=0x56CE))
[root@localhost ~]# echo "$a.$b.$c.$d:$e"
127.0.0.1:22222

0100007F:DE72

[root@localhost ~]# ((d=0x01))
[root@localhost ~]# ((c=0x00))
[root@localhost ~]# ((b=0x00))
[root@localhost ~]# ((a=0x7F))
[root@localhost ~]# ((e=0xDE72))
[root@localhost ~]# echo "$a.$b.$c.$d:$e"
127.0.0.1:56946

总结一下:
● server.py与client.py各自打开tcp socket 描述符,该描述符指向内存中的socket结构体
● socket结构体描述了关于TCP的所有信息,其中通过TCP 4元组找到对端的通信节点
● socket将用户数据以及自身结构数据封装完成之后会交给底层的TCP协议,然后是IP协议、链路层信息,最后通过物理链路到达对端
● 对端也会依次解包,直至将发送端数据写入到指定的内存当中,最终由应用程序读取(本文中的server.py或client.py)

                        client.py                         server.py
                        +---------------+                 +---------------+
                        |pid:14202      |                 |pid:14199      |
                        |    +-----+    |                 |    +-----+    |
                        |    |fd:3 |    |                 |    |fd:4 |    |
                        |    +-----+    |                 |    +-----+    |
                        +---------------+                 +---------------+
                                |                                 |
             user space         |                                 |
             +---------------------------------------------------------------------+
             kernel space       |                                 |
                                |                                 |
                                v                                 v
                         +------+-------+                  +------+-------+
                         |socket:[28728]|                  |socket:[99155]|
                         +------+-------+                  +------+-------+
                                |                                 |
                                |                                 |
                                v                                 v
                           +----+----+                       +----+----+
                           | socket  |                       | socket  |
                           +----+----+                       +----+----+
                                |                                 |
                                |                                 |
                                v                                 v
                               ++---------------------------------+-
                               |                tcp                |
                               +------------------------------------


四、小结

● TCP连接中最重要的是TCP四元组,而进程打开TCP socket描述符可以找到四元组信息,从而确定双方的IP和port
● 通过socket文件描述符可以找到内存中的socket结构体,获取到TCP连接的详细信息,包括必备四元组、文件的inode、时间、出队入队状态等等
● 1个进程可以创建多个TCP连接,也就是创建多个socket文件描述符,这由该进程能够打开的文件数量限制(ulimit -n

五、参考资料

http://www.cs.colostate.edu/~gersch/cs457/CS457_tutorial2.pdf
https://gist.github.com/jkstill/5095725



至此,本文结束
在下才疏学浅,有撒汤漏水的,请各位不吝赐教...

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

推荐阅读更多精彩内容