python socket 编程

socket 基于C/S架构 通常两个文件一个服务端(server) 一个客户端(client)

import socket 模块

socket 类型&解释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
socket.AF_UNIX  # 只能够用于单一的Unix系统进程间通信

socket.AF_INET # ipV4

socket.AF_INET6 # ipv6

socket.SOCK_STREAM # 流式socket , for TCP

socket.SOCK_DGRAM # 数据报式socket , for UDP

socket.SOCK_SEQPACKET # 可靠的连续数据包服务

socket.SOCK_RAW
# 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;
# 其次,SOCK_RAW也可以处理特殊的IPv4报文;
# 此外,利用原始套接字,可以通过 IP_HDRINCL 套接字选项由用户构造IP头

创建TCP Socket:

1
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

创建UDP Socket:

1
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

通过s = socket.socket()方法

我们可以获得一个socket对象s,也就是通常说的获取了一个“套接字”,该对象具有以下方法(更新中):

server端:

1
2
3
4
5
6
7
8
9
10
11
s.bind((host, port))
# 绑定地址(host,port)到套接字,在AF_INET下,以元组(host,port)的形式表示地址。

s.listen(1)
# 开始监听 listen(可以挂起的最大连接数量,至少为一)

conn, addr = s.accept()
# 被动接受连接(阻塞式),等待连接
# 并返回(conn,address)
# (通信对象(可以用来发送&接收数据) , 链接地址)

client端:

1
2
3
4
5
6
7
8
9
s.connect((host, port)) 
# 客户端向服务器端发起连接。
# 一般address的格式为元组(host,port)
# 如果连接出错,返回socket.error错误。

s.connect_ex()
# connect()函数的扩展版本
# 出错时返回出错码,而不是抛出异常

公共方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
s.recv(bufsize)
# 接收数据,数据以bytes类型返回,bufsize指定要接收的最大数据量
# 比如s.recv(1024)

s.send()
# 发送数据。返回值为要发送的字节数量

s.sendall()
# 完整发送数据
# 将数据发送到连接的套接字,但在返回之前会尝试发送所有数据
# 成功返回None,失败则抛出异常

s.recvform()
# 接收UDP数据,与recv()类似,但返回值是(data,address)
# 其中data是包含接收的数据,address是发送数据的套接字地址

s.sendto(data,address)
# 发送UDP数据,将数据data发送到套接字
# address是形式为(ipaddr,port)的元组
# 指定远程地址。返回值是发送的字节数。

s.close()
# 关闭套接字,必须执行

s.getpeername()
# 返回套接字的远程地址,通常值是一个元组(ip, port)

s.getsockname()
# 返回套接字自己的地址,通常值是一个元组(ip, port)

s.setsockopt(level,optname,value)
# 设置给定套接字选项的值

s.getsockopt(level,optname[.buflen])
# 返回套接字选项的值

s.settimeout(time)
# 设置套接字操作的超时期,timeout是一个浮点数,单位是秒。
# 值为None表示没有超时期。
# 一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect())

s.gettimeout()
# 返回当前超时期的值,单位是秒
# 如果没有设置超时期,则返回None

s.fileno()
# 返回套接字的文件描述符

s.setblocking(flag)
# flag为0,套接字为非阻塞模式,否则将套接字设为阻塞模式(默认值)
# 非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常。

s.makefile()
# 创建一个与该套接字相关连的文件

注意事项

  1. Python3以后,socket传递的都是bytes类型的数据

    字符串需要先转换一下,string.encode()即可;

    另一端接收到的bytes数据想转换成字符串

    只要bytes.decode()一下就可以。

  2. 在正常通信时,accept()和recv()方法都是阻塞的。

    所谓的阻塞,指的是程序会暂停在那,一直等到有数据过来。

socket编程思路

服务端:

  1. 创建套接字,绑定套接字到本地IP和端口:

    socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    s.bind()

  2. 开始监听连接:

    s.listen()

  3. 进入循环, 不断接受客户端请求

    s.accept()

  4. 接收传来的数据,或者发送数据给对方

    s.recv()

    s.sendall()

  5. 传输完毕后,关闭套接字

    s.close()

客户端

  1. 创建套接字,连接服务器地址

    s.socket()

    s.connect()

  2. 连接后发送数据和接收数据

    s.sendall()

    s.recv()

  3. 传输完毕后,关闭套接字:

    s.close()