了解网络编程的基本概念
了解七层协议与四层协议
掌握TCP/IP协议
掌握UDP协议
掌握Socket套接字
熟练应用TCP编程
熟练应用UDP编程
Socket对象的常用方法
方法名称 | 功能描述 |
bind((ip,port)) | 绑定IP地址和端口 |
listen(N) | 开始TCP监听,N表示操作系统挂起的最大连接数量,取值范围1-5之间,一般设置为5 |
accept() | 被动接收TCP客户端连接,阻塞式 |
connect((ip,port)) | 主动初始化TCP服务端连接 |
recv(size) | 接收TCP数据,返回值为字符串类型,size表示要接收的最大数据量 |
send(str) | 发送TCP数据,返回值是要发送的字节数量 |
sendall(str) | 完整发送TCP数据,将str中的数据发送到连接的套接字,返回之前尝试发送所有数据,如果成功为None,失败抛出异常 |
recvfrom() | 接收UDP数据,返回值为一个元组(data,address),data表示接收的数据,address表示发送数据的套接字地址 |
sendto(data,(ip,port)) | 发送UDP数据,返回值是发送的字节数 |
close() | 关闭套接字 |
TCP编程
TCP编程客户端与服务器端启动运行有先后,先启动运行服务器端再启动运行客户端,连接建立之后双方谁先发送数据都行,以下举例默认客户端先发送。
TCP服务器端流程
- 使用socket类创建一个套接字对象
- 使用bind((ip,port))方法绑定IP地址和端口号
- 使用listen()方法开始TCP监听
- 使用accept()方法等待服务端连接
- 使用recv()/send()方法接收/发送数据
- 使用close()关闭套接字
from socket import socket, AF_INET, SOCK_STREAM
#AF_INET 用于Internet之间的进程通信
#SOCK_STREAM 表示的是TCP协议编程
#(1)创建socket对象
server_socket = socket(AF_INET, SOCK_STREAM)
#(2)绑定IP地址和端口号
ip='127.0.0.1'#等同于local
port=8888#端口的范围
server_socket.bind((ip, port))
#(3)开始TCP监听
server_socket.listen(5)
print('服务已启动')
#(4)等到客户端连接
client_socket,client_addr=server_socket.accept()#系列解包赋值
#(5)接收数据
data=client_socket.recv(1024)
print('客户端发来的数据为:',data.decode('utf-8'))
#(6)关闭套接字
server_socket.close()
TCP客户端流程
- 使用socket类创建一个套接字对象
- 使用connect((host,port))设置连接的主机ip和主机设置的端口号
- 使用recv()/send()方法接收/发送数据
- 使用close()关闭套接字
import socket
#创建socket对象
client_socket=socket.socket()
#设置IP地址和端口号
ip='127.0.0.1'
port=8888
client_socket.connect((ip,port))
print('连接成功')
#发送数据
enter=input('请输入要发送的内容:')
client_socket.send(enter.encode('utf-8'))#.encode('utf-8')编码
#关闭套接字
client_socket.close()
print('发送完毕')
上述只能接收/发送一次,一次之后就会结束
使用while循环可以实现聊天
服务端
# 导入模块
import socket
# 创建套接字对象
socket_obj = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定ip、端口
ip = '127.0.0.1'
port = 8888
socket_obj.bind((ip, port))
# 开始监听
socket_obj.listen(5)
print('服务已启动')
# 等待服务端连接
client_socket, addr = socket_obj.accept()
# 接收数据.decode('utf-8')是用utf-8解码
data = client_socket.recv(1024).decode('utf-8')
# 开始循环接收/发送
while data != 'bye':
if data != '':
print('接收到的数据是:', data)
# 准备要发送的数据
info = input('请输入要发送的数据:')
client_socket.send(info.encode('utf-8'))
# 退出循环条件
if data == 'bye' or info == 'bye':
break
# 继续等待接收数据
data = client_socket.recv(1024).decode('utf-8')
# 关闭
client_socket.close()
socket_obj.close()
客户端
# 导入模块
import socket
# 创建套接字对象
client_socket = socket.socket()
# 设置连接的主机和端口号
ip = '127.0.0.1'
port = 8888
client_socket.connect((ip, port))
print('连接已完成')
# 开始循环接收/发送
info = '' #
while info != 'bye':
# 准备要发送的数据
send_data = input('输入要发送的信息:')
client_socket.send(send_data.encode('utf-8'))
# 退出循环条件
if send_data == 'bye':
break
# 继续等待接收数据
info = client_socket.recv(1024).decode('utf-8')
print('收到!', info)
client_socket.close()
UDP编程
UDP编程接收方与发送方启动无先后,但是先启动运行发送方,数据会丢包。
UDP接收方流程
- 使用socket类创建一个套接字对象
- 使用bind((ip,port))方法绑定IP地址和端口号
- 使用recvfrom()方法接收数据
- 准备要回复的数据,使用send()方法回复对方
- 使用close()关闭套接字
#导入模块
from socket import socket, AF_INET, SOCK_DGRAM
#1创建socket对象
recv_socket = socket(AF_INET, SOCK_DGRAM)
#2绑定ip和端口号
recv_socket.bind(('127.0.0.1', 8888))
#3接收数据
send_data, addr = recv_socket.recvfrom(1024)
print('收到了信息:', send_data.decode('utf-8'))
#4回复
data = input('请回复:')
recv_socket.sendto(data.encode('utf-8'), addr)
#5关闭
recv_socket.close()
UDP发送方流程
- 使用socket类创建一个套接字对象
- 准备发送数据
- 指定接收方的ip地址和端口
- 使用sendto()发送数据
- 用recvfrom()接收来自接收方的数据
- 关闭
# 导入模块
from socket import socket, AF_INET, SOCK_DGRAM
# 1创建socket对象
send_socket = socket(AF_INET, SOCK_DGRAM)
# 2准备发送的数据
data = input('请输入要发送的数据:')
# 3指定接收方的ip地址和端口
ip_port = ('127.0.0.1', 8888)
# 4发送数据
send_socket.sendto(data.encode('utf-8'), ip_port)
# 5用recvfrom()接收来自接收方的数据
recv_data, addr = send_socket.recvfrom(1024)
print('接收到的数据为:', recv_data.decode('utf-8'))
# 6关闭
send_socket.close()
同样的上述只能接收/发送一次,一次之后就会结束
使用while循环可以实现聊天
接收端
#导入模块
from socket import socket, AF_INET, SOCK_DGRAM
#建立套接字对象
sefer_socket = socket(AF_INET, SOCK_DGRAM)
#绑定ip和端口
sefer_socket.bind(('127.0.0.1',8888))
#recvfrom()接收发送方的消息
user_data,addr=sefer_socket.recvfrom(1024)
#进入循环聊天
while user_data.decode('utf-8')!='bye':
print('用户发来消息:',user_data.decode('utf-8'))
#准备要回复的数据,.encode('utf-8')编码,发送
info=input('请输入需要回复的信息:')
sefer_socket.sendto(info.encode('utf-8'),addr)
#判断退出条件
if user_data.decode('utf-8')=='bye' or info == 'bye':
break
#如果不退出就继续监听
user_data, addr = sefer_socket.recvfrom(1024)
#关闭
sefer_socket.close()
发送端
#导入模块
from socket import socket, AF_INET, SOCK_DGRAM
#创建套接字对象
user_socket = socket(AF_INET, SOCK_DGRAM)
#指定接收方的IP和端口号
ip_port = ('127.0.0.1', 8888)
#判断循环
while True:
#准备要发送的内容,.encode('utf-8')进行编码
data = input('请输入要发送的内容:')
user_socket.sendto(data.encode('utf-8'), ip_port)
#判断是否退出循环
if data == 'bye':
break
info, addr = user_socket.recvfrom(1024)
if info.decode('utf-8') == 'bye' :
break
#.decode('utf-8')解码
print('您收到了', info.decode('utf-8'))
#关闭
user_socket.close()