1 网络软件
客户端:c/s架构 , client/server
浏览器:BS架构 , brower/server
2 基于socket模块实现网络通信
socket参数的详解
socket.socket(family=AF_INET,type=SOCK_STREAM,proto=0,fileno=None)
创建socket对象的参数说明:
| family | 地址系列应为AF_INET(默认值),AF_INET6,AF_UNIX,AF_CAN或AF_RDS。 (AF_UNIX 域实际上是使用本地 socket 文件来通信) |
| type | 套接字类型应为SOCK_STREAM(默认值),SOCK_DGRAM,SOCK_RAW或其他SOCK_常量之一。 SOCK_STREAM 是基于TCP的,有保障的(即能保证数据正确传送到对方)面向连接的SOCKET,多用于资料传送。 SOCK_DGRAM 是基于UDP的,无保障的面向消息的socket,多用于在网络上发广播信息。 |
| proto | 协议号通常为零,可以省略,或者在地址族为AF_CAN的情况下,协议应为CAN_RAW或CAN_BCM之一。 |
| fileno | 如果指定了fileno,则其他参数将被忽略,导致带有指定文件描述符的套接字返回。 与socket.fromfd()不同,fileno将返回相同的套接字,而不是重复的。 这可能有助于使用socket.close()关闭一个独立的插座。 |
TCP(Transmission Control Protocol)可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。使用TCP的应用:Web浏览器;电子邮件、文件传输程序。
UDP(User Datagram Protocol)不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。

服务端套接字函数
s.bind() 绑定(主机,端口号)到套接字
s.listen() 开始TCP监听
s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来
客户端套接字函数
s.connect() 主动初始化TCP服务器连接
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
公共用途的套接字函数
s.recv() 接收TCP数据
s.send() 发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
s.sendall() 发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
s.recvfrom() 接收UDP数据
s.sendto() 发送UDP数据
s.getpeername() 连接到当前套接字的远端的地址
s.getsockname() 当前套接字的地址
s.getsockopt() 返回指定套接字的参数
s.setsockopt() 设置指定套接字的参数
s.close() 关闭套接字
面向锁的套接字方法
s.setblocking() 设置套接字的阻塞与非阻塞模式
s.settimeout() 设置阻塞套接字操作的超时时间
s.gettimeout() 得到阻塞套接字操作的超时时间
面向文件的套接字的函数
s.fileno() 套接字的文件描述符
s.makefile() 创建一个与该套接字相关的文件
服务端:
accept,阻塞:等待客户端来连接。
recv, 阻塞:等待客户端发来数据。
客户端:
connect,阻塞:一直在连接,直到连接成功才往下运行其他代码。
recv, 阻塞:等待服务端发来数据。
2.1 案例1:基于TCP简单的连接通信
服务端:
1 #创建服务端socket对象 2 server = socket.socket() 3 4 #绑定服务端IP和端口到套接字 5 server.bind(('192.168.13.126',8000)) 6 7 #同时可访问5个 8 server.listen(5) #服务端等待连接的限制 9 10 #等待客户端来连接,如果不来,就一直等待 11 #addr是客户端的地址信息 12 #conn是客户端与服务的连接的介质(对象) #这里的介质的意思是服务端与客户端相连的介质
|
客户端:
1 import socket 2 3 #创建客户端socket对象 4 5 client = socket.socket() 6 7 8 9 # 客户端向服务端发起连接请求 10 11 # 阻塞,去连接,直到连接成功后才会继续向下走。 12 13 client.connect(('192.168.13.126',8000)) 14 15 16 17 # # 链接上服务端后,向服务端发送消息 18 19 client.send(b'hello') 20 21 22 23 # 客户端等待服务端给他发送消息 24 25 data = client.recv(1024) 26 27 print(data) 28 29 30 31 # 关闭自己 32 33 client.close() |
2.2 案例2:基于TCP交互式循环单播
服务端:
1 import socket 2 server = socket.socket() 3 server.bind(('192.168.13.126',8001)) 4 5 server.listen(5) 6 7 while True: #服务器无限循环 8 conn,addr = server.accept() 9 while True: #通讯循环 10 data = conn.recv(1024) 11 print(data.decode('utf-8')) 12 if data == b'exit': 13 break 14 data = input("回答:") 15 response = data 16 conn.send(response.encode('utf-8')) 17 conn.close()
|
客户端:
1 import socket 2 3 cli = socket.socket() 4 5 cli.connect(('192.168.13.126',8001)) 6 7 while True: 8 name = input("请输入姓名:") 9 cli.send(name.encode('utf-8')) 10 if name == 'exit': 11 break 12 response = cli.recv(1024) 13 print(response.decode('utf-8')) 14 15 cli.close() |
2.3 案例3:关于客户端单方面断开连接报错的问题
1 import socket 2 3 server = socket.socket() 4 IP_PORT = ('127.0.0.1',8899) 5 server.bind(IP_PORT) 6 server.listen(5) 7 8 while 1: 9 print("server is working......") 10 conn,addr = server.accept() 11 while 1: 12 try: #针对Windows系统,当服务端与客户端连接时,客户端单方面断开连接,服务端就会报错 13 data = conn.recv(1024) 14 if len(data) == 0: #针对Linux系统当服务端与客户端连接时,客户端单方面断开连接,服务端接受的数据就为空 15 break 16 if data == b'exit': 17 break 18 conn.send(b"hello") 19 except Exception as e: 20 break 21 conn.close()
1 import socket 2 3 client = socket.socket() 4 client.connect(('127.0.0.1',8899)) 5 6 while 1: 7 s = input(">>>").encode('utf8') 8 client.send(s) 9 10 p = client.recv(1024).decode('utf8') 11 print(p)
2.3 补充:
为什么要网络通信发送的是字节?而不是字符串?
py3, send/recv 都是字节(所谓字节,8位1字节)
py2, send/recv 都是字符串
python3中的字符串中是默认Unicode编码,所以需要转码压缩
python2中默认字符串就是ascii编码



浙公网安备 33010602011771号