Python socket 编程
使用 Python37 调试
1.服务端
# -*- coding: UTF-8 -*- import random import socket if __name__ == '__main__': s = socket.socket() # 创建socket对象 s.bind(('127.0.0.1', 123)) # 绑定地址和端口 s.listen(5) # 开始 TCP监听 参数5指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为 1,大部分应用程序设为 5 就可以了。 s.settimeout(50) # 设置等待连接时间(秒),不设则永久等待 while True: print('服务端开始监听') conn, address = s.accept() # 有客户端访问了,返回的是连接对象和客户端地址,阻塞等待 print('连接对象:{}'.format(conn)) print('客户端地址:{}'.format(address)) data = conn.recv(1024) # bufsize 表示接收最大字节数,小于 bufsize 则全接收,大于 bufsize 则截断 print('接收数据:{}'.format(data)) print('数据类型:{}'.format(type(data))) # Python37 接收到是 Bytes 型 Python27是 str msg = str(random.randint(0, 99999999)).encode('utf-8') conn.sendall(msg) # 发送随机数给客户端 print('服务端给客户端发送信息成功:{}'.format(msg)) conn.close() # 关闭连接 print('服务端停止监听')
2.客户端
# -*- coding: UTF-8 -*- import socket if __name__ == '__main__': s = socket.socket() s.settimeout(10) # 设置超时时间(连接或接收数据) s.connect(('127.0.0.1', 123)) # 连接服务端 s.sendall('I am client data'.encode('utf-8')) # 发送数据 data = s.recv(1024) # Python37 接收到是 Bytes 型 Python27是 str print('接收数据:{}'.format(data)) print('type(data):{}'.format(type(data))) s.close()
运行
服务端
服务端开始监听 连接对象:<socket.socket fd=1412, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 123), raddr=('127.0.0.1', 53739)> 客户端地址:('127.0.0.1', 53739) 接收数据:b'I am client data' 数据类型:<class 'bytes'> 服务端给客户端发送信息成功:b'64716933' 服务端开始监听
客户端
接收数据:b'64716933' type(data):<class 'bytes'>
3.异常情况
(1)[WinError 10054] 远程主机强迫关闭了一个现有的连接。
当客户端在接收数据时,服务端关闭(手动),则客户端抛出异常10054
当服务端在接收数据时,客户端关闭(手动),则服务端抛出异常10054
手动指的是自己关闭了运行的cmd
(2)[WinError 10061] 由于目标计算机积极拒绝,无法连接。
当客户端连接服务端时,使用了错误的PORT,客户端抛出异常10061
当客户端连接服务端时,使用了错误的IP,客户端抛出异常10061
(3)[WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。
当服务端绑定了一个IP和PORT, 再次绑定时,服务端抛出异常10048
(4)[WinError 10053] 你的主机中的软件中止了一个已建立的连接。
当客户端在接收数据时,服务端关闭(自动),则客户端抛出异常10053
自动指的是代码自动调用到s.close()
该代码可复现
# -*- coding: UTF-8 -*- import random import socket import time if __name__ == '__main__': s = socket.socket() # 创建socket对象 s.bind(('127.0.0.1', 123)) # 绑定地址和端口 s.listen(5) # 开始 TCP监听 参数5指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为 1,大部分应用程序设为 5 就可以了。 s.settimeout(50) # 设置等待连接时间(秒),不设则永久等待 while True: print('服务端开始监听') conn, address = s.accept() # 有客户端访问了,返回的是连接对象和客户端地址,阻塞等待 print('连接对象:{}'.format(conn)) print('客户端地址:{}'.format(address)) data = conn.recv(1024) # bufsize 表示接收最大字节数,小于 bufsize 则全接收,大于 bufsize 则截断 print('接收数据:{}'.format(data)) print('数据类型:{}'.format(type(data))) # Python37 接收到是 Bytes 型 Python27是 str msg = str(random.randint(0, 99999999)).encode('utf-8') conn.sendall(msg) # 发送随机数给客户端 print('服务端给客户端发送信息成功:{}'.format(msg)) break conn.close() # 关闭连接 print('服务端停止监听')
# -*- coding: UTF-8 -*- import socket import time if __name__ == '__main__': s = socket.socket() # s.settimeout(5) # 设置超时时间(连接或接收数据) s.connect(('127.0.0.1', 123)) # 连接服务端 # time.sleep(5) while True: s.sendall('I am client data'.encode('utf-8')) # 发送数据 data = s.recv(1024) # Python37 接收到是 Bytes 型 Python27是 str print('接收数据:{}'.format(data)) print('type(data):{}'.format(type(data))) time.sleep(10) s.close()
运行
服务端
服务端开始监听 连接对象:<socket.socket fd=1432, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 123), raddr=('127.0.0.1', 56007)> 客户端地址:('127.0.0.1', 56007) 接收数据:b'I am client data' 数据类型:<class 'bytes'> 服务端给客户端发送信息成功:b'36744020' 服务端停止监听
客户端