linux socket pair
AF_UNIX
AF_UNIX 用于本地,通过socket文件通信 , 不用经过cpu对包解析,放到网卡, 内核直接放到对应的socket缓冲文件。如果客户端与服务端通过socket文件通信,那通过netstat命令, 能找到客户端与服务端的连接关系吗?
请看测试实例:
server.pl
#! /usr/bin/perl -wuse strict;
use IO::Socket::UNIX qw( SOCK_STREAM SOMAXCONN );my $SOCK_PATH = '/tmp/test.sock';
unlink($SOCK_PATH) if -e $SOCK_PATH;my $server = IO::Socket::UNIX->new(Type => SOCK_STREAM(),Local => $SOCK_PATH,Listen => SOMAXCONN,
)or die("Can't create server socket: $!\n");while (1) {my $connection = $server->accept;if (fork() == 0) {print "** New connection received **\n";$connection->autoflush(1);my $count = 1;while (my $line = <$connection>) {if ($line){chomp($line);$connection->print($count . ' -> ' . $line . "\n"); print "Received and replied to $count '$line'\n";$count++;}}close $connection;exit;}
}
client.pl
#!/usr/bin/perl -wuse strict;
use IO::Socket::UNIX qw( SOCK_STREAM );my $SOCK_PATH = '/tmp/test.sock';
my $client = IO::Socket::UNIX->new(Type => SOCK_STREAM(),Peer => $SOCK_PATH
)or die("Can't connect to server: $!\n");$client->autoflush(1);## Listen for replies
if (fork() == 0) {while (my $line = <$client>) {if ($line){chomp($line);print("Recv: '" . $line . "'\n");}}
}## Send something
while(1){for my $itm ('Alpha','Beta','Gamma','Delta'){print("Send: " . $itm . "\n");print($client $itm . "\n") or warn("Can't send: $!\n"); # send to server, \n terminates}sleep 5
}print "** Client Finished **\n";
通过lsof netstat 查找客户端连接的socket文件
查看进程id
[root@localhost ~]# ps auxf | grep server.pl
root 19083 0.0 0.1 135592 4324 pts/1 S+ 19:18 0:00 | \_ perl server.pl
root 19092 0.0 0.1 135592 2700 pts/1 S+ 19:18 0:00 | \_ perl server.pl
root 19157 0.0 0.0 112708 984 pts/3 S+ 19:18 0:00 \_ grep --color=auto server.pl
[root@localhost ~]# ps auxf | grep client.pl
root 19090 0.0 0.1 135592 4308 pts/2 S+ 19:18 0:00 | \_ perl client.pl
root 19091 0.0 0.0 135592 2344 pts/2 S+ 19:18 0:00 | \_ perl client.pl
root 19211 0.0 0.0 112708 984 pts/3 S+ 19:19 0:00 | \_ grep --color=auto client.pl
查看服务端文件占用
[root@localhost ~]# lsof -p 19092 | grep sock
perl 19092 root 3u unix 0xffff93dbd27ba400 0t0 70144 /tmp/test.sock
perl 19092 root 4u unix 0xffff93dbd1ee5800 0t0 70145 /tmp/test.sock
[root@localhost ~]# netstat -anlp | grep 19092
unix 3 [ ] STREAM CONNECTED 70145 19092/perl /tmp/test.sock
查看客户端文件占用
[root@localhost ~]# lsof -p 19090 |grep sock
perl 19090 root 3u unix 0xffff93dbd1ee3c00 0t0 70162 socket
[root@localhost ~]# lsof -p 19091 |grep sock
perl 19091 root 3u unix 0xffff93dbd1ee3c00 0t0 70162 socket[root@localhost ~]# netstat -anlp | grep 19090
unix 3 [ ] STREAM CONNECTED 70162 19090/perl
[root@localhost ~]# netstat -anlp | grep 19091
[root@localhost ~]# [root@localhost ~]# ll /proc/19090/fd/
total 0
lrwx------. 1 root root 64 Apr 27 19:21 0 -> /dev/pts/2
lrwx------. 1 root root 64 Apr 27 19:21 1 -> /dev/pts/2
lrwx------. 1 root root 64 Apr 27 19:18 2 -> /dev/pts/2
lrwx------. 1 root root 64 Apr 27 19:21 3 -> socket:[70162]
通过以上几种方法查看客户端的情况, 我们只知道它有建立一个socket连接,但是具体连接到那个socket文件,并不知道。那根据lsof 输出的 device=0xffff93dbd1ee3c00, 以及node=70162, 能找到对应的socket文件吗?
[root@localhost ~]# stat /tmp/test.sock File: ‘/tmp/test.sock’Size: 0 Blocks: 0 IO Block: 4096 socket
Device: fd00h/64768d Inode: 67785956 Links: 1
Access: (0755/srwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Context: unconfined_u:object_r:user_tmp_t:s0
Access: 2020-04-27 19:18:33.922022962 +0800
Modify: 2020-04-27 19:18:28.245022727 +0800
Change: 2020-04-27 19:18:28.245022727 +0800Birth: -
[root@localhost ~]#
发现实际 /tmp/test.sock 的inode是67785956 显然这俩不是一个概念。
继续看,0xffff93dbd1ee3c00应该是一个内存地址,那我们在proc下找找。
[root@localhost ~]# grep -Irn "ffff93dbd1ee3c0" /proc/net
/proc/net/unix:80:ffff93dbd1ee3c00: 00000003 00000000 00000000 0001 03 70162
也看不出具体是那个文件(但对于如tcp连接,其实在/proc/net/tcp中是可以找到连接的 ip:port 信息的)
那要怎么才能找对对应连接的socket文件呢,
最后还是在外文上找到了资料,https://unix.stackexchange.com/questions/16300/whos-got-the-other-end-of-this-unix-socketpair/190606#190606
通过ss命令或打印peer值
ss命令
对于内核大于3.3, 可以使用ss命令
[root@localhost ~]# ss | grep 70162
u_str ESTAB 0 0 * 70162 * 70145
u_str ESTAB 0 0 /tmp/test.sock 70145 * 70162
[root@localhost ~]#
70162在ss命令种,表示Port, 在netstat种又表示 I-Node, 有什么不一样吗?
打印peer内存地址
对于没有ss命令的环境,则可以从上述的内存地址找到答案。即 0xffff93dbd1ee3c00
利用之前一篇博客搭建的内核调试环境,参见: https://www.jianshu.com/p/caff00d28b5e
这次我们使用kcore来查看内核的当前运行情况
gdb /usr/lib/debug/lib/modules/3.10.0-957.el7.x86_64/vmlinux /proc/kcore
Core was generated by `BOOT_IMAGE=/vmlinuz-3.10.0-957.el7.x86_64 root=/dev/mapper/centos-root ro crashk'.
#0 0x0000000000000000 in irq_stack_union ()
(gdb) print ((struct unix_sock*) 0xffff93dbd1ee3c00)->peer
$1 = (struct sock *) 0xffff93dbd1ee5800
(gdb) quit
[root@localhost ~]# lsof | grep 0xffff93dbd1ee5800
perl 19092 root 4u unix 0xffff93dbd1ee5800 0t0 70145 /tmp/test.sock
[root@localhost ~]#
Linux内核关于unix_sock的定义
/* The AF_UNIX socket */
struct unix_sock {/* WARNING: sk has to be the first member */struct sock sk;struct unix_address *addr;struct path path;struct mutex readlock;struct sock *peer;struct list_head link;atomic_long_t inflight;spinlock_t lock;unsigned char recursion_level;unsigned long gc_flags;
#define UNIX_GC_CANDIDATE 0
#define UNIX_GC_MAYBE_CYCLE 1struct socket_wq peer_wq;wait_queue_t peer_wake;
};
与我们的客户端代码是一致的
my $client = IO::Socket::UNIX->new(
Type => SOCK_STREAM(),
Peer => $SOCK_PATH
)or die("Can't connect to server: $!\n");
该方法即将peer的内存地址打印出来,对应的就是path信息了。 有了这些排查方法,我们就能找到client连接的是哪个socket文件以及服务端进程, 方便定位问题。
linux socket pair相关推荐
- Linux Socket编程入门——浅显易懂
文章目录 1. 概述 2. Socket 3. 网络字节序 4. sockaddr 数据结构 5. 网络套接字API函数 5.1 socket() 5.2 bind() 5.3 listen() ...
- Linux Socket基础介绍
Linux Socket函数库是从Berkeley大学开发的BSD UNIX系统中移植过来的.BSD Socket接口是众多Unix系统中被广泛支持的TCP/IP通信接口,Linux下的Socket程 ...
- python封装api linux_python Socket编程-python API 与 Linux Socket API之间的关系
python socket编程 by SA19225409 地址协议家族 Python 支持 AF_UNIX. AF_NETLINK. AF_TIPC 和 AF_INET 家族 AF_UNIX 基于本 ...
- linux socket关闭连接 shutdown与close
在Linux socket关闭连接的方法有两种分别是shutdown和close,首先看一下shutdown的定义 #include<sys/socket.h>int shutdown(i ...
- Linux socket关闭连接shutdown与close
在Linux socket关闭连接的方法有两种分别是shutdown和close,首先看一下shutdown的定义 #include<sys/socket.h> int shutdown( ...
- linux socket使用情况 ss -s ss -t -a | cat /proc/net/socketstat
linux socket使用情况 ss -s ss -t -a | cat /proc/net/socketstat Linux系统中,查看SOCKET使用情况可以使用ss命令. 1.命令格式: ss ...
- 对于linux socket与epoll配合相关的一些心得记录
对于linux socket与epoll配合相关的一些心得记录 没有多少高深的东西,全当记录,虽然简单,但是没有做过测试还是挺容易让人糊涂的 int nRecvBuf=32*1024;//设置为32K ...
- linux 查看socket fd,linux socket中select()函数以及FD_ZERO FD_SET FD_CLR FD_ISSET
linux socket非阻塞编程时常见到如下的code: socket s; ..... fd_set set; ..... struct timeval tv; while(1) { FD ...
- linux socket高性能服务器处理框架
这个博客很多东西 http://blog.csdn.net/luozhonghua2014/article/details/37041765 思考一种高性能的服务器处理框架 1.首先需要一个内存池,目 ...
最新文章
- 科学家研究:生女有撇步 多钙少碰香蕉
- 前端笔记-使用vue-cli(脚手架)开发TodoList
- 排序算法比较以及代码展示
- 电脑显示器尽快触摸化
- 当深度学习遇见自动文本摘要
- 小技巧 - 同步苹果手机和 Windows 的提醒事项
- Layui多文件上传,java后台(servlet实现)
- 【采样算法】拉丁超立方采样
- Tower of Hanoi(汉诺塔)详解
- mt6737电池状态监测
- sql server中的怎么把数值型转换为字符串
- cad画不规则实体_如何在CAD中徒手画不规则的图形
- 计算机类部队文职好考吗,“军队文职”招考遇冷,8000余岗位无人报考,是铁饭碗不香了吗...
- RM电控(更新中……
- 基于java前行国家公务员模拟笔试系统计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署
- 公司如何选择适合的管理软件?
- android三国2,三国群英传2威力加强版安卓
- Windows动态库注册和取消注册
- 根据LabelImg标注的方框大小批量裁剪图片
- matlab绘图(学习中)
热门文章
- 2021年山东省安全员B证考试题及山东省安全员B证找解析
- 拥抱Transformer,图解NLP处理流程四部曲
- 【Web_UI自动化_Python3_12306查询余票/车次_seleniumkeysselectXpath定位】12306火车票官方订票网站,查询余票/车次,自动化测试案例
- 第一个Python代码-猜数字
- 中谷教育python精讲_中谷教育Python视频(课件、源码)推荐
- 使input文本框中文字居中
- mysql函数临时表_MySQL函数中创建临时表
- xshell连接不了服务器显示22端口,解决Xshell不从22端口连接服务器
- 罗永浩宣布退网创业;谷歌研究员“走火入魔”事件曝光:认为AI已具备人格,被罚带薪休假;Wasmer 2.3 发布|极客头条
- SpringCloud(下)