2016-08-25 3 views
0

Swift에서 Minecraft 서버의 상태를 쿼리하려고합니다. 나는 here을 보았지만, 어떻게해야 할지를 알 수 없다. 나는 그것을 발견하고 mc 서버를 쿼리 할 수있는 Java 클래스를 분석했다. (찾을 수는 here), Swift에서 구현하는 방법을 모른다. Swift에서 패킷을 전송 한 다음 서버에서 패킷을받는 방법은 무엇입니까?Swift에서 Minecraft Server List Ping을 구현하려고 시도했습니다.

import UIKit 

var str = "Hello, playground" 

var inputStream: NSInputStream? 
var outputStream: NSOutputStream? 

NSStream.getStreamsToHostWithName("0.0.0.0", port: 25577, inputStream: &inputStream, outputStream: &outputStream) 
outputStream?.open() 
inputStream?.open() 
//while(true){ 
//get input 
//} 
let bytes : [CChar] = [0x01] 
let data = NSData(bytes: bytes, length: 1) 
//let data: NSData = "this is a test string".dataUsingEncoding(NSUTF8StringEncoding)! 
outputStream?.write(UnsafePointer<UInt8>(data.bytes), maxLength: data.length) 




NSLog("asdfasdf") 
var buffer = [UInt8](count: 4096, repeatedValue: 0) 
inputStream?.read(&buffer, maxLength: buffer.count) 
inputStream?.read(&buffer, maxLength: buffer.count) 
inputStream?.read(&buffer, maxLength: buffer.count) 
+0

완료 방법을 보여주는 몇 가지 샘플 코드를 게시 할 수 있습니까? 자바? 나는 대부분의 사람들이 마인 크래프트 프로토콜을 모른다는 것을 모험한다. –

+0

다음은 Java로 작성된 파일입니다. https://gist.github.com/zh32/7190955 – spacegeek224

+0

@DavidShaw 질문에 추가했습니다. – spacegeek224

답변

0

조금 늦었지만,이 정확한 코드는 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) 
    } 
    } 
} 
관련 문제