套接字及其编程(python)

基本介绍:

socket(套接字)是一个抽象层,允许应用程序将I/O接入网络,与网络中其他应用程序进行通信

类型:

流式套接字(SOCK-STREAM)

可靠的、面向连接的双向数据传输服务,能实现数据无差错、无重复的发送,常用于TCP

数据报套接字(SOCK-DGRAM)

无连接、不可靠的双向数据传输服务,可能丢失、重复或乱序,常用于UDP

原始套接字(SOCK-RAW)

对较低层协议如(IP或ICMP)进行直接访问,常用于网络协议分析、检验新的网络协议实现

使用原始套接字进行网络通信基本步骤:

  • 创建原始套接字、设置套接字选项和创建并填充相应协议头
  • 用sendto()函数将组装好的数据发送出去
  • 使用recvfrom()函数接受数据并解析
  • 关闭套接字

特点:

普通的套接字无法处理ICMP、IGMP等网络报文,而原始套接字可以,但通常仅限于高级用户或管理员运行的程序使用

ICMP协议:

全称为Internet Control Message Protocol(Internet控制报文协议)

ICMP是TCP/IP模型中网络层的重要成员。两个常用的网络管理命令ping(用来测试网络可达性)和tracert(用来显示到达目的主机的路径)都利用ICMP协议来实现网络功能

ICMP报文:

  • IP报头(至少20字节)
  • ICMP报头(至少8字节)
  • ICMP报文(数据部分)
当IP报头中的协议字段值为1时,就说明这是一个ICMP报文

ICMP报头:

  • 类型:差错报文(取值1-127)、信息报文(取值128以上)
  • 代码:与类型共同标识详细类型
  • 校验和:对包括数据部分在内整个ICMP的校验和,以检验在传输过程中是否出现差错

ICMP报文类型:

  • 0 ——回送应答
  • 3 ——目标不可达
  • 4 ——原点抑制
  • 5 ——重定向或改变路由
  • 8 ——回送请求
  • 9 ——路由器公告
  • 10 ——路由器请求
  • 11 ——超时
  • 13 ——时间戳请求
  • 14 ——时间戳应答
  • 17 ——地址子网请求
  • 18 ——地址子网应答
ping中就包括了请求(类型值为8)和应答(类型值为0)的ICMP报文

协议数据包的封装:

使用Python的struct模块来完成

  • pack()函数,把数据封装成字节流
pack(fmt, v1, v2, ...) #其中fmt为给定格式,vi为封装对象
  • unpack()函数,将字节流解析返回数组
unpack(fmt, string) #其中fmt为给定格式,string为解析字对象
  • calcsize()函数,计算给定格式占用的内存
calcsize(fmt)  #其中fmt为给定格式
fmt支持的格式

套接字编程:

引入套接字模块

import socket
#或者,本文代码默认为使用下一种
from socket import * 

套接字的创建

socket()函数

返回创建套接字

mySocket = socket(socket_family, socket_type, protocol = 0)
  • socket_family为协议类型,可以为:AF_INET #IPv4(默认), AF_INET6 #IPv6, AF_UNIX #只能够只能够用于单一的Unix系统进程间通信
  • socket_type为套接字类型,可以为SOCK_STREAM #流式socket , for TCP (默认), SOCK_DGRAM #数据报式socket , for UDP, SOCK_RAW #原始套接字
  • protocol为制定协议,可以为0(自动选择合适的协议)或使用getprotobyname()函数指定ICMP、UDP等(指定协议)
icmp = getprotobyname("icmp")   #指定ICMP协议
rawsocket = socket(AF_INET, SOCK_RAW, icmp)

服务器端功能:

bind()函数

无返回值,将套接字绑定到目标地址的端口

serverSocket.bind(address) #其中address为以元组(host, port) 的形式表示的地址,host为str类型IP地址,port为int类型端口号(以下都是)

listen()函数

无返回值,开始监听

serverSocket.listen(backlog) #其中backlog为拒绝连接前可以监听的最大数量,至少为1

accept()函数

返回connectSocket和address,接收一个连接

connectSocket, address = serverSocket.accept() #其中connextSocket为新创建的用于接收和发送数据的套接字对象,address为连接客户端的地址

客户端功能:

connect()函数

无返回值,连接到服务器地址的套接字

clientSocket.connect(address) #其中address为以元组(host, port) 的形式表示的地址

connext_ex()函数

返回连接情况,成功返回0,失败返回error的值,连接到服务器地址的套接字

clientSocket.connect_ex(address) #其中address同上

通用功能:

recv()函数

返回发送方的报文内容字符,接受套接字的数据

data = commonSocket.recv(bufsize) #其中bufsize为接受的最大数据量

recvfrom()函数

返回发送方的报文内容字符串和发送方地址,接受套接字的数据

data, address = commonSocket.recvfrom(length) #其种length为指定报文最大长度

send()函数

返回值为发送的字节数(也可以没有),发送字符串类型报文内容到连接的套接字

发送前如果报文为str类型,需要用encode()进行编码,encode()可以指定编码类型,没有参数输入时默认为utf-8

commonSocket.send(data) #其中data为bytes类型的报文内容
commonSocket.send(data.encode("utf-8")) #其中data为str类型的报文内容

sendto()函数

返回值为发送的字节数(也可以没有),发送字符串类型报文内容到指定地址的套接字

发送前如果报文为str类型,需要用encode()进行编码,encode()可以指定编码类型,没有参数输入时默认为utf-8

commonSocket.sendto(data, address) #其中data为bytes类型的报文内容,address为以元组(host, port) 的形式表示的地址
commonSocket.sendto(data.encode("utf-8"), address) #其中data为str类型的报文内容,address为以元组(host, port) 的形式表示的地址

settimeout()函数

无返回值,设定套接字操作时限

commonSocket.settimeout(time) #其中time为float类型的操作时限

close()函数

无返回值,关闭套接字

commonSocket.close()
UDP:面向数据报的不可靠传输服务
TCP:面向字节流的可靠传输服务

UDP套接字编程特点

客户端和服务器之间不需要建立连接

  • 发送数据之前不需要先握手
  • 每一个分组都携带有收发双方的IP地址和端口号
  • 接受方收到的分组中提取发送方的IP地址和端口号

分组可能丢失或者乱序到达接收方

使用UDP的客户端-服务器交互过程

TCP套接字编程特点

发送数据之前客户端和服务器需要建立连接

  • 服务器创建服务器(监听)套接字,等待客户端的连接请求
  • 客户端创建客户端套接字,并向服务器发起连接请求
  • 服务器创建一个新的连接套接字处理与该客户端的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值