在Solaris系统上如何查看进程打开的端口?或者如何查看端口是由哪个进程打开的?
背景知识:
- procfs文件系统
- 库libproc
/*
* 遍历进程
* pids : 所有进程的id
* pidcnt : pids的大小
* return进程数
*/
int enum_procs_list(int pids[], int pidcnt);
/*由进程id得到fd的路径:"/proc/<pid>/fd"*/
int get_procs_fdpath(int pid, char *path, int size);
int get_procs_sockfs(int pid, char *path)
{
char sock_fpath[32];
char buf[256], ipbuf[16];
DIR *dirp;
struct dirent *dentp;
struct stat statb;
int sockfd;
struct sockaddr *saddr = (struct sockaddr *)buf;
socklen_t len = 0;
struct sockaddr_in *sin;
int retval = 0;
struct ps_prochandle *pshandle = 0;
if ((dirp = opendir(path)) == NULL) {
return -1;
}
while ((dentp = readdir(dirp)) != NULL) {
if (!isdigit(dentp->d_name[0])) { continue; }
strcat(strcpy(fpath, path), dentp->d_name); sockfd = atoi(dentp->d_name);
if (stat(fpath, &statb) == -1) {
continue;
}
if (S_ISSOCK(statb.st_mode)) {
if (pshandle == 0)
pshandle = Pgrab((pid_t)pid, 0x02, &retval);
if (phandle != 0) {
len = sizeof(buf);
if (pr_getsockname(pshandle, sockfd, saddr, &len) != -1) {
sin = (struct sockaddr_in *) saddr;
printf("pid %d/t/t%s.%u", pid, inet_ntop(AF_INET, &sin->sin_addr, ipbuf, sizeof(ipbuf)), ntohs(sin->sin_port));
}
len = sizeof(buf);
if (pr_getpeername(pshandle, sockfd, saddr, &len) != -1) {
sin = (struct sockaddr_in *) saddr;
printf("pid %d/t/t%s.%u", pid, inet_ntop(AF_INET, &sin->sin_addr,
ipbuf, sizeof(ipbuf)), ntohs(sin->sin_port));
}
}
}
if (pshandle)
Prelease(pshandle);
closedir(dirp);
return 1;
}
说明:
- struct ps_prochandle、Pgrab、Prelease、pr_getsockname、pr_getpeername都来自libproc。
- 文中只附主要的代码,其他的代码较易从网络获得。
- 文中程序未对sock进行区分(AF_UNIX, AF_INET, AF_INET6...)
- 除了本文中的方式外,还可以参考开源项目lsof,也可以实现进程端口映射。