Ich arbeite an diesem UDP-Client-Beispiel in Swift. Ich habe einen Bridging-Header, um die entsprechenden C-Header-Dateien zu integrieren. In dem Beispielprogramm kann ich die richtige Anzahl von Bytes sehen, die gesendet und empfangen werden. Aber wenn ich versuche, die Nachricht an die Konsole zu drucken, bekomme ich nichts. Es sollte der rote Pfeil erscheint eine Meldung sein:UDP Messaging in Swift Bytes lesen, aber keine Nachricht
Ich bin bereit, es zu wetten, ist etwas klein, aber ich habe seit gestern Abend auf diese und ich bin mit der Ratlosigkeit gewichen. Irgendwelche Vorschläge?
UdpClient:
import Foundation
enum UDPClientError: Int, LocalizedError {
case noSocket = -999
case bindSocket
case badAddress
case alreadyInProgress
case setupForNonBlocking
case threadLock
var localizedDescription: String {
switch self {
case .alreadyInProgress:
return "operation in progress"
case .badAddress:
return "Address string given is not valid"
case .bindSocket:
return "Could not bind socket"
case .noSocket:
return "Could not obtain socket"
case .setupForNonBlocking:
return "Could not setup socket for non-blocking operation"
case .threadLock:
return "Could not obtain thread lock"
}
}
}
class UDPClient {
private var mySocket: Int32 = 0
private var myAddress = sockaddr_in()
private var otherAddress = sockaddr_in()
let name: String
private var receiveQueue = [String]()
private var sendQueue = [String]()
private var okToRun = false
private var threadLock = pthread_mutex_t()
init(name: String, port: UInt16, otherIPAddress: String, otherPort: UInt16) throws {
self.name = name
mySocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
if mySocket == -1 {
throw UDPClientError.noSocket
}
if fcntl(mySocket, F_SETFL, O_NONBLOCK) == -1 {
throw UDPClientError.setupForNonBlocking
}
myAddress.sin_family = sa_family_t(AF_INET)
myAddress.sin_port = in_port_t(port)
myAddress.sin_addr.s_addr = in_addr_t(INADDR_ANY)
let retCode = withUnsafeMutablePointer(to: &myAddress) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
bind(mySocket, UnsafeMutablePointer<sockaddr>($0), socklen_t(MemoryLayout<sockaddr_in>.size))
}
}
if retCode == -1 {
throw UDPClientError.bindSocket
}
otherAddress.sin_family = sa_family_t(AF_INET)
otherAddress.sin_port = in_port_t(otherPort)
var buffer: [Int8] = Array(otherIPAddress.utf8CString)
if inet_aton(&buffer, &otherAddress.sin_addr) == 0 {
throw UDPClientError.badAddress
}
if pthread_mutex_init(&threadLock, nil) != 0 {
throw UDPClientError.threadLock
}
print("done")
}
func beginOperation() {
okToRun = true
_ = Thread.detachNewThreadSelector(#selector(process), toTarget: self, with: nil)
//processThread.start()
}
func endOperation() {
okToRun = false
}
func send(message: String) {
pthread_mutex_lock(&threadLock)
sendQueue.append(message)
pthread_mutex_unlock(&threadLock)
}
func getMessage() -> String? {
pthread_mutex_lock(&threadLock)
let flag = receiveQueue.isEmpty
pthread_mutex_unlock(&threadLock)
if flag {
print("no message")
return nil
}
pthread_mutex_lock(&threadLock)
let message = receiveQueue.remove(at: 0)
pthread_mutex_unlock(&threadLock)
return message
}
@objc private func process() {
//let bufferLimit = 1024
var buffer = [UInt8](repeating: 0, count: 1024)
buffer.removeAll(keepingCapacity: true)
var slen = socklen_t(MemoryLayout<sockaddr_in>.size)
print("Process running for " + name)
var bytesRead = 0
var bytesSent = 0
while okToRun {
if sendQueue.isEmpty == false {
buffer.removeAll(keepingCapacity: true)
pthread_mutex_lock(&threadLock)
buffer.append(contentsOf: sendQueue.remove(at: 0).utf8)
pthread_mutex_unlock(&threadLock)
bytesSent = withUnsafeMutablePointer(to: &otherAddress) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
sendto(mySocket, buffer, buffer.count, 0, UnsafePointer<sockaddr>($0), socklen_t(MemoryLayout<sockaddr_in>.size))
}
}
if bytesSent != -1 {
print("First buffer character: \(buffer[0])")
print("\(name): sendto() bytes sent: \(bytesSent)")
}
buffer.removeAll(keepingCapacity: true)
}
bytesRead = withUnsafeMutablePointer(to: &otherAddress) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
recvfrom(mySocket, UnsafeMutableRawPointer(mutating: buffer), 1024, 0, UnsafeMutablePointer<sockaddr>($0), &slen)
}
}
if bytesRead != -1 {
print("\(name): Bytes read = \(bytesRead) bytes: \(buffer)")
pthread_mutex_lock(&threadLock)
receiveQueue.append(String(bytes: buffer, encoding: .utf8)!)
pthread_mutex_unlock(&threadLock)
slen = socklen_t(MemoryLayout<sockaddr_in>.size)
}
bytesRead = 0
bytesSent = 0
} // end processing loop
} // end process
}
UDP-Bridging-Rubrik:
#ifndef UDP_Bridging_Header_h
#define UDP_Bridging_Header_h
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <pthread.h>
#endif /* UDP_Bridging_Header_h */
Hauptdatei ausprobieren Client:
import Foundation
var client_1: UDPClient?
var client_2: UDPClient?
do {
try client_1 = UDPClient(name: "Client A", port: 9990, otherIPAddress: "192.168.2.4", otherPort: 9992)
}
catch {
print(error.localizedDescription)
}
do {
try client_2 = UDPClient(name: "Client B", port: 9992, otherIPAddress: "192.168.2.4", otherPort: 9990)
}
catch {
print(error.localizedDescription)
}
if client_1 != nil && client_2 != nil {
client_1!.send(message: "Try this out")
client_1!.beginOperation()
client_2!.beginOperation()
Thread.sleep(forTimeInterval: 5.0)
if let msg = client_2!.getMessage() {
print(msg)
}
}
Ich habe einige Änderungen basierend auf Ihren Aussagen vorgenommen. Aber ich finde, dass der Aufruf removeAll() notwendig ist, um die Anzahl der Bytes auf ein Minimum zu beschränken. Ich habe jetzt Arbeitscode und werde es bald veröffentlichen ... – xBACP
@PartialFrozenOJ: Senden und Empfangen sind unabhängig, und ich habe nicht gesagt, dass Sie removeAll() überall in Ihrem Code entfernen sollten. Wenn Sie jedoch Bytes empfangen, muss das Array die Anzahl der Elemente enthalten, die Sie als Längenparameter an recvfrom übergeben. –
ok dann habe ich dich missverstanden. – xBACP