开发流程:
软件开发模式:C/S架构 B/S架构
C/S架构:Client/Server架构
客户端5步走:
导入模块
import socket
创建套接字对象(IPV4/TCP协议):
tcp_client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
和服务器端套接字建立连接,参数要求是元组类型:
tcp_client_socket.connect(('192.168.13.22',8080))
发送数据到服务器端:
data = ''.encode()
tcp_client_socket.send(data)
**注意:**数据必须是字节流类型,encode(编码格式)方法 把字符串类型的数据转换为bytes字节流数据
decode()方法 把字节流转换为字符串,编码格式可以是gbk和utf-8,可以不写
接收服务器端返回的数据recv(字节大小)
recv_data = tcp_client_socket.recv(1024).decode()
print('服务器端响应',recv_data)
关闭套接字对象
tcp_client_socket.close()
完整客户端代码:
import socket
# 创建套接字对象
tcp_client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 和服务器端套接字建立连接
tcp_client_socket.connect(('192.168.13.30',8080))
# 发送数据到服务器端
data = '收到请回答'.encode('gbk')
tcp_client_socket.send(data)
#接受服务器端返回的数据recv(字节大小)
recv_data = tcp_client_socket.recv(1024).decode('gbk')
print('服务器端响应:',recv_data)
#关闭套接字对象
tcp_client_socket.close()
服务端7步走:
导入模块
import socket
创建套接字对象:
tcp_server_socker = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
使用bind(host,port)方法绑定ip和端口:
tcp_server_socker.bind(('192.168.13.30',8080))
**注意:**绑定的ip地址可以为空,代表绑定本机
使用listen()监听端口:
tcp_server_socker.listen(128)
**注意:**最大处理量为128,多余的请求需要等待
准备接受客户端的连接请求:
server_client_socket,ip_port = tcp_server_socker.accept()
**注意:**返回一个元组,有两个元素,前者是一个套接字对象(是客户端连接到的服务器的信息),后者是一个客户端的ip和端口号
**注意:**accept()有返回值,会产生一个新的套接字,后续的交互都通过这个新套接字来实现
用新的套接字接收客户端的请求:
recv_data = server_client_socket.recv(1024).decode('gbk')
处理并返回数据给客户端:
server_client_socket.send('返回客户端的信息').encode(‘gbk')
关闭套接字对象:
server_client_socket.close()
tcp_client_socket.close()
完整服务端代码:
# 导入模块
import socket
# 创建服务端对象
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 设置端口号
tcp_server_socket.bind(('',8080))
# 设置监听
tcp_server_socket.listen(128)
# 等待客户端发出请求,接受客户端的IP地址和端口号
server_client_socket,ip_port = tcp_server_socket.accept()
# 打印接受的内容
print('客户端的ip地址和端口号:',ip_port)
# 接收客户端发送的数据
recv_data = server_client_socket.recv(1024)
# 获取数据长度
recv_data_length = len(recv_data)
print('接收的数据长度为:',recv_data_length)
#对接收到的数据进行编码
recv_content = recv_data.decode('gbk')
print('客户端发送的数据为:',recv_content)
# 回复客户端(准备向客户端发送数据)
send_data = '已收到请求'.encode('gbk')
server_client_socket.send(send_data)
# 关闭服务端与客户端的套接字连接
server_client_socket.close()
# 关闭客户端的连接
tcp_server_socket.close()
服务端线程化:
# 导入模块
import socket
import threading
# 处理客户端的请求操作
def handle_client_request(service_client_socket,ip_port):
# 循环接收客户端发送的数据
while True:
# 接收客户端发送的数据
recv_data = service_client_socket.recv(1024)
if recv_data == True:
try:
print(recv_data.decode('gbk'),ip_port)
# 回复
# reply = input('请输入要回复客户端的内容:')
service_client_socket.send('服务器崩溃了...'.encode('gbk'))
except UnicodeDecodeError:
print(recv_data.decode('utf-8'), ip_port)
# 回复
# reply = input('请输入要回复客户端的内容:')
service_client_socket.send('服务器崩溃了...'.encode('utf-8'))
else:
print('客户端下线了:',ip_port)
break
# 终止和客户端进行通信
service_client_socket.close()
if __name__ == '__main__':
# 创建tcp服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 设置端口号复用,让程序退出端口号立即释放
tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
# 绑定端口号
tcp_server_socket.bind(('', 8080))
#设置监听
tcp_server_socket.listen(128)
# 循环等待接收客户端的连接请求
while True:
# 等待接收客户端的请求
service_client_sockeet,ip_port = tcp_server_socket.accept()
print('客户端连接成功:',ip_port)
# 创建子线程,不同的子线程接收不同的客户端消息
sub_thread = threading.Thread(target=handle_client_request,args=(service_client_sockeet,ip_port))
# 守护主线程
sub_thread.setDaemon(True)
# 启动子线程
sub_thread.start()
**注意:**端口复用:为了让端口在服务器断开后迅速释放
在创建的套接字对象下面
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)