有點晚了,但是......我碰巧在Swift中寫了一次精確的代碼。我前一段時間寫過,所以我不完全確定它是否還能正常工作,但它應該。此外,這將需要https://github.com/vapor/sockets的套接字庫。這絕對不是我曾經寫過的最漂亮的代碼,但我真的只是匆匆扔在一起,所以......這就是:
import Foundation
import Sockets
import Dispatch
public class MinecraftQuery {
let STATISTIC: UInt8 = 0x00
let HANDSHAKE: UInt8 = 0x09
private let socket: UDPInternetSocket
private var challenge: [UInt8]? = nil
private var challengeNumber: Int32 = 0
private var last_connect_time = Date(timeIntervalSinceReferenceDate: 0)
private var response_received = false
private var update_queued = false
//toggle to prevent multple active connections
private var connection_active = false
public var serverInfo: [String: String] = [:]
public var playerList: [String] = []
init? (hostname: String, port: Port = 19132) {
do {
socket = try UDPInternetSocket(address: InternetAddress(hostname: hostname, port: port))
} catch (let error) {
debugPrint(error)
return nil
}
print("query_init working")
}
func connect() {
do {
try socket.sendto(data: [0xFE, 0xFD, self.HANDSHAKE, 0x01, 0x02, 0x03, 0x04 ])
// Should receive challenge
let temp_recv = try socket.recvfrom(maxBytes: 20)
guard temp_recv.sender == socket.address else {
print("Received query challenge from unknown source. Ignoring.")
return
}
guard temp_recv.data.starts(with: [self.HANDSHAKE, 1, 2, 3, 4]) else {
print("Received invalid challenge data. Ignoring.")
return
}
self.challenge = temp_recv.data
if let challengeString = String(utf8String: Array(challenge![5...].map({ (byte) -> Int8 in
Int8(byte)
}))) {
guard let challengeNumber = Int32(challengeString)?.byteSwapped else {
print("Could not convert challenge to number. Ignoring.")
return
}
self.challengeNumber = challengeNumber
}
} catch (let error) {
debugPrint(error)
}
}
func query() {
let queryData = Data([0xFE, 0xFD, self.STATISTIC, 1, 2, 3, 4]) + Data(bytes: &self.challengeNumber, count: 4) + [0, 0, 0, 0]
do {
try self.socket.sendto(data: Array(queryData))
let statisticRecv = try self.socket.recvfrom()
guard statisticRecv.sender == socket.address else {
print("Received statistics from unknown source. Ignoring.")
return
}
guard statisticRecv.data.starts(with: [0, 1, 2, 3, 4]) else {
print("Received invalid statistics data. Ignoring")
return
}
var resultsDict: [String: String] = [:]
let binStrings = statisticRecv.data[5...].split(separator: 0)
var playerHeaderIDX = 0
for index in 0..<binStrings.count {
if index % 2 == 0 {
if String(bytes: binStrings[index], encoding: .ascii) == "\u{01}player_" {
playerHeaderIDX = index
break
}
resultsDict[String(bytes: binStrings[index], encoding: .ascii)!] = String(bytes: binStrings[index + 1], encoding: .ascii)!
}
}
self.serverInfo = resultsDict
self.playerList = binStrings[(playerHeaderIDX + 1)...].map({ (binString) -> String in
if let returnString = String(bytes: binString, encoding: .ascii) {
return returnString
} else {
return ""
}
})
} catch (let error) {
debugPrint(error)
}
}
}
你可以張貼展示它是如何在做了一些示例代碼Java的?我敢打賭,大多數人不知道Minecraft協議。 –
這裏是我發現用Java編寫的文件:https://gist.github.com/zh32/7190955 – spacegeek224
我將它添加到問題@DavidShaw – spacegeek224