208 lines
6.1 KiB
Go
208 lines
6.1 KiB
Go
|
|
/*
|
|||
|
|
本程序为云算力平台卖方客户端,主要提供以下功能:
|
|||
|
|
1,将云算力平台上的卖方身份和GPU主机绑定
|
|||
|
|
2,通过本客户端,可以使云算力平台获取到卖方具体每台机器的详细参数,包括GPU型号、显存容量等
|
|||
|
|
3,卖方可通过本客户端自动匹配买方的挖矿需求,即卖方无需再买方下单后手动操作挖矿
|
|||
|
|
|
|||
|
|
卖家在启动客户端之前需要注意以下事项:
|
|||
|
|
1,确定客户端执行主机已经配置好挖矿环境,包括显卡驱动、挖矿软件(指定挖矿软件)、执行权限等,即执行本客户端的用户可以手动通过挖矿软件进行挖矿
|
|||
|
|
2,如果要对本机GPU进行移除(拔出GPU)操作,云算力平台会同步移除对应的GPU
|
|||
|
|
3,如果在相关GPU有租约且没有在平台申请故障处理的情况下直接移除(拔出)GPU,会导致产生罚没,因此在有租约的情况下要移除故障GPU,请第一时间前往平台申请故障处理,在平台确认后再进行移除GPU的操作
|
|||
|
|
4,如果要对本机GPU进行更换(拔出后又新插入GPU)操作,云算力平台会重新读取GPU数据,如果更换型号相同,则会按原有配置上架,如果更换的型号不同,则需在更换后前往卖家中心手动调整上架配置
|
|||
|
|
5,如果在相关GPU有租约且没有在平台申请故障处理的情况下直接更换GPU,可能会导致产生罚没,因此在有租约的情况下要更换故障GPU,请第一时间前往平台申请故障处理,在平台确认后再进行更换GPU的操作
|
|||
|
|
*/
|
|||
|
|
package client
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
message "client/internal/msg"
|
|||
|
|
"client/internal/src"
|
|||
|
|
"client/internal/src/linux"
|
|||
|
|
"client/internal/utils"
|
|||
|
|
"encoding/json"
|
|||
|
|
"fmt"
|
|||
|
|
"log"
|
|||
|
|
"net"
|
|||
|
|
"runtime"
|
|||
|
|
"strings"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
type Client struct {
|
|||
|
|
Auth string
|
|||
|
|
MachineCode string
|
|||
|
|
ServerConn net.Conn // 服务连接
|
|||
|
|
GPUs map[int]message.GPU // {"gpu编号": message.GPU{}, ...}
|
|||
|
|
os *src.SystemServer
|
|||
|
|
osName string
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func newClient(url string) *Client {
|
|||
|
|
var client = &Client{}
|
|||
|
|
// 读取身份文件
|
|||
|
|
auth, err := utils.ReadFile("./auth")
|
|||
|
|
if err != nil {
|
|||
|
|
log.Fatalf("获取客户端身份失败:%v", err)
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
client.Auth = auth
|
|||
|
|
|
|||
|
|
os := src.NewSystemServer()
|
|||
|
|
sys := runtime.GOOS
|
|||
|
|
if sys == "linux" {
|
|||
|
|
linux_ := linux.NewLinuxClient(auth)
|
|||
|
|
os.ResiterSystem("linux", linux_)
|
|||
|
|
} else {
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
client.os = os
|
|||
|
|
client.osName = sys
|
|||
|
|
|
|||
|
|
// 读取主机MAC地址信息
|
|||
|
|
var machine_code string
|
|||
|
|
machine_code, err = os.GetMACAddress(sys)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Fatalln(err)
|
|||
|
|
panic("获取当前主机信息失败,程序已退出,请检查网络后重新启动本客户端。")
|
|||
|
|
}
|
|||
|
|
utils.WirteFile("./machinecode", machine_code)
|
|||
|
|
|
|||
|
|
client.MachineCode = machine_code
|
|||
|
|
|
|||
|
|
gpus, err := os.GetGPUInfo(sys)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Fatalln(err)
|
|||
|
|
panic("获取当前主机GPU数据失败,程序已退出,请检查GPU驱动等程序后重新启动本客户端。")
|
|||
|
|
}
|
|||
|
|
client.GPUs = gpus
|
|||
|
|
server_conn, err := net.Dial("tcp", url)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Fatalf("客户端连接到服务器失败:%v", err)
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
defer server_conn.Close()
|
|||
|
|
|
|||
|
|
client.ServerConn = server_conn
|
|||
|
|
return client
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (c *Client) sendMachineCode() {
|
|||
|
|
var msg message.ServerMsg
|
|||
|
|
msg.ID = c.Auth + "." + c.MachineCode
|
|||
|
|
msg.Method = "auth.machineCode"
|
|||
|
|
msg.Params = c.GPUs
|
|||
|
|
msgByte, err := json.Marshal(msg)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Fatalf("消息(%v)序列化失败:%v", msg, err)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
c.send(msgByte)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (c *Client) receiveMsg() {
|
|||
|
|
buffer := make([]byte, 1024)
|
|||
|
|
|
|||
|
|
for {
|
|||
|
|
n, err := c.ServerConn.Read(buffer)
|
|||
|
|
if err != nil {
|
|||
|
|
if err.Error() == "EOF" {
|
|||
|
|
// 服务端关闭连接时,退出接收循环
|
|||
|
|
log.Println("服务端关闭了连接")
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
log.Println("接收数据失败:", err)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
msgByte := buffer[:n]
|
|||
|
|
go c.handleReceiveMsg(msgByte)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (c *Client) send(msg []byte) {
|
|||
|
|
_, err := c.ServerConn.Write(msg)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Fatalf("发送消息失败,消息内容:%s", string(msg))
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (c *Client) handleReceiveMsg(msg []byte) {
|
|||
|
|
var data message.ServerMsg
|
|||
|
|
err := json.Unmarshal(msg, &data)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Fatalf("解析接收到的消息失败:%v", err)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
parts := strings.Split(data.ID, ".")
|
|||
|
|
if len(parts) != 2 {
|
|||
|
|
log.Fatalf("解析通信协议(server->client)失败")
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
auth, machine_code := parts[0], parts[1]
|
|||
|
|
if c.Auth != auth || c.MachineCode != machine_code {
|
|||
|
|
log.Fatalf("客户端接收到错误的服务端消息")
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
switch data.Method {
|
|||
|
|
case "mining.req":
|
|||
|
|
mining_msg, ok := data.Params.(message.ConfigurationMiningMsg)
|
|||
|
|
if ok {
|
|||
|
|
// 这里开始挖矿
|
|||
|
|
err := c.os.Mining(c.osName, mining_msg)
|
|||
|
|
if err != nil {
|
|||
|
|
sendMsg_str := message.ServerMsgResp{
|
|||
|
|
ID: c.Auth + "." + c.MachineCode,
|
|||
|
|
Result: false,
|
|||
|
|
Data: err,
|
|||
|
|
}
|
|||
|
|
sendMsg_byte, err := json.Marshal(sendMsg_str)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Fatalf("序列化%v失败:%v", sendMsg_str, err)
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
c.send(sendMsg_byte) // 返回失败消息
|
|||
|
|
}
|
|||
|
|
// 挖矿开始
|
|||
|
|
data := message.ConfigurationMiningResp{
|
|||
|
|
Coin: mining_msg.Coin,
|
|||
|
|
Algo: mining_msg.Algo,
|
|||
|
|
Pool: mining_msg.Pool,
|
|||
|
|
PoolUrl: mining_msg.PoolUrl,
|
|||
|
|
WorkerID: mining_msg.WorkerID,
|
|||
|
|
WalletAddress: mining_msg.WalletAddress,
|
|||
|
|
WatchUrl: "", // 这里需要根据矿池自动生成
|
|||
|
|
}
|
|||
|
|
sendMsg_str := message.ServerMsgResp{
|
|||
|
|
ID: c.Auth + "." + c.MachineCode,
|
|||
|
|
Result: true,
|
|||
|
|
Data: data,
|
|||
|
|
}
|
|||
|
|
sendMsg_byte, err := json.Marshal(sendMsg_str)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Fatalf("序列化%v失败:%v", sendMsg_str, err)
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
c.send(sendMsg_byte) // 返回成功消息
|
|||
|
|
} else {
|
|||
|
|
sendMsg_str := message.ServerMsgResp{
|
|||
|
|
ID: c.Auth + "." + c.MachineCode,
|
|||
|
|
Result: false,
|
|||
|
|
Data: fmt.Errorf("错误的params数据结构:%v", mining_msg),
|
|||
|
|
}
|
|||
|
|
sendMsg_byte, err := json.Marshal(sendMsg_str)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Fatalf("序列化%v失败:%v", sendMsg_str, err)
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
c.send(sendMsg_byte) // 返回失败消息
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func Star() {
|
|||
|
|
url := "xxxx"
|
|||
|
|
client := newClient(url)
|
|||
|
|
client.sendMachineCode()
|
|||
|
|
go client.receiveMsg() // 开始接收服务端消息
|
|||
|
|
}
|