python 调用linux内核api_python Socket编程-python API 与 Linux Socket API之间的关系

本文介绍 Python 中的 Socket 编程,包括地址协议家族、端口号管理等内容,并通过一个持续通信的服务端与客户端示例,展示如何使用 Python 的 socket 模块实现 TCP 通信。此外,还对比了 Python Socket API 和 Linux Socket API 的实现。
摘要由CSDN通过智能技术生成

python socket编程

by SA19225409

地址协议家族

Python 支持 AF_UNIX、 AF_NETLINK、 AF_TIPC 和 AF_INET 家族

AF_UNIX 基于本地文件通信

AF_INET 基于网络通信

AF_NETLINK 基于用户级别和内核级别代码之间的进程通信

AF_TIPC 基于服务器集群通信,不需要ip寻址

端口

有效的端口号范围为 0~65535(尽管小于 1024 的端口号预留给了系统)。如果你正在使用 POSIX 兼容系统(如 Linux、 Mac OS X 等),那么可以在通过cat /etc/services 查看你文件中预留端口号的列表。

端口号可以分为三个范围:“已知端口”、“注册端口”以及“动态和/或专用端口”。

“已知端口”是从 0 到 1023 的端口。

“注册端口”是从 1024 到 49151 的端口。

“动态和/或专用端口”是从 49152 到 65535 的端口。理论上,不应为服务分配这些端口。

Demo

此次python实现的“hello/hi”版本不是一次通话就结束,是持续的通信,除非一方主动断开,另外利用python的with语句能够捕捉一方连接中断或者其他异常,并进行处理。

服务端

#socket()->bind()->listen()->accept()->recv()-send()

#!/usr/bin/env python

# coding=utf-8

from socket import *

HOST = ''

PORT = 2345

BUFSIZE = 1024

ADDR = (HOST,PORT)

#创建AF_INET地址族,TCP的套接字

with socket(AF_INET,SOCK_STREAM) as tcpSerSock:

#绑定ip和端口

tcpSerSock.bind(ADDR)

#监听端口,是否有请求

tcpSerSock.listen(5)

while True:

print("waiting for connect!!")

#accept() 是阻塞的

tcpClientSock,addr = tcpSerSock.accept()

print("the client: ",addr,"is connecting")

with tcpClientSock:

#使用一个while循环,持续和客户端通信,直到客户端断开连接或者崩溃

while True:

data = tcpClientSock.recv(BUFSIZE)

#判断客户端是否断开连接

if not data:

break;

print("client: ",data.decode("utf-8"))

#相应客户端请求

msg = input("server: ")

tcpClientSock.sendall(msg.encode("utf-8"))

#客户端退出

print("client ",addr,"exit!")

客户端

#socket()->connect()->send()->recv()

#!/usr/bin/env python

# coding=utf-8

from socket import *

HOST = "192.168.8.188"

# HOST = "127.0.0.1"

PORT = 2345

ADDR = (HOST,PORT)

with socket(AF_INET,SOCK_STREAM) as tcpCliSock:

tcpCliSock.connect(ADDR)

with tcpCliSock:

while True:

msg = input("client:")

tcpCliSock.sendall(msg.encode('utf-8'))

data=tcpCliSock.recv(1024)

if not data:

break

print("server: ",data.decode("utf-8"))

print("server crash")

启动服务器进程和客户端进程

python server.py

python client.py

通信结果如下:

netstat

netstat 查看 socket 及其状态的信息

如下结果可以看到客户端进程和服务器进程通过tcp建立连接

isof

isof 命令使用 -i 参数可以查看打开的 socket 连接的 COMMAND, PID(process id) 和 USER(user id),下面的输出就是打印客户端的连接信息,可以通过man lsof,查看详细信息

tcpdump

tcpdump抓包分析,因为有一个端口号是2345,所以tcpdump的一个参数就可以设为端口号,详细的参数可自行百度

tcpdump 抓包只能看到端口号,如上图是符合通信过程的:客户端(52316端口)向服务端(2345)发送hello,服务端回复hi。

对比python socket API 和 linux socket API

使用strace命令跟踪对比发现,python的API就是对Linux的API进行封装。

strace python ./client.py

Python

Linux

socket(AF_INET,SOCK_STREAM)

socket(PF_INET,SOCK_STREAM,IPPRPTO_IP)=3

bind((host,port))

bind(3,{sa_family=AF_INET,sin_port=htons(2345),sin_addr("0.0.0.0")},16)=0

accept()

accept(3,{sa_family=AF_INET,sin_port=htons(2345),sin_addr("192.168.8.xx)},[16]))=4

recv(BUFERSIZE)

recvfrom(4,buf_address,lenth,0,NULL,NULL)

sendall(msg.encode("utf-8))

sendto(4,msg,sizeof(msg),0,NULL,0)

connect((host,port))

connect(3,{sa_family=AF_INET,sin_port=htons(2345),sin_addr("192.168.8.xx)},[16]))=4

表格中的3 ,4表示文件描述符,熟悉linux系统的朋友对文件描述符想必不会陌生,但可以注意到服务器进程产生了两个文件描述符,先是一个3,对应socket创建,而后accept之后,又产生了一个文件描述符4,对应客户端;而客户端始终只有一个3,对应当前连接,可以看到二者的文件描述符是无必然相等关系的。

参考资料:

Python核心编程(第3版) [美] Wesley Chun 著 孙波翔 李斌 李晗 译

博客:tcpdump抓包命令详解.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值