0

I am currently trying to create a simple TCP Peer2Peer communication between two computers via Swift. On my on computer it works fine, but when I move one instance to another computer, it receives messages on the second PC but is not able to send any messages.

I have disabled my Firewall and tried it with a Hotspot on my phone. When I use my Rust Peer2Peer connector, it totally works in any case.

What am I doing wrong?

Here is my full code

P2P.swift

import Foundation
import SocketSwift


class P2P {
    
    
    var reciever: Reciever?
    var sender: Sender?
    
    init(serverPort: Int, otherIp: String, otherPort: Int, ownIp: String) {
        print("Data: \(ownIp):\(serverPort) -> \(otherIp):\(otherPort)")
        _ = Task {
            sender = Sender(serverPort: serverPort, ownIp: ownIp)
            sender?.acceptClient()
            while(true) {
                do {
                    try sender?.writeStream(message: readLine() ?? "No")
                } catch let error {
                    print("Error while sending Data \(error)")
                }
            }
        }
        self.reciever = Reciever(otherIp: otherIp, otherPort: otherPort)
        
        
        while(true){ //programm 
            
        }
    }
}

Reciever.swift

import Foundation
import SocketSwift

class Reciever { //AKA Client for RECIEVING MESSAGES
    let prefix = "RECIEVER: "
    var client: Socket? = nil //on this channel I will recieve data
    init(otherIp: String, otherPort: Int) {
        
        _ = clientConnectAsync(otherPort: otherPort, otherIp: otherIp)
        
        while(true) {
            do {
                print(try readStreamAsync(size: 10) ?? "Nothing to read")
            } catch let error {
                print(prefix + "Error while reading \(error)")
            }
        }
    }
    
    
    
    
    
    //read whats in the incoming pip and retuns a string. takes the size of how many input it should take
    private func readStreamAsync(size: Int) throws -> String? {

        var buffer = [UInt8](repeating: 0, count: size) // allocate buffer
     
        var result: String = "";
        _ = try client?.read(&buffer, size: size) // throws the data into the buffer var
        var isEmpty: Bool = true
        for i in 0...size-1 {
            if buffer[i] != 0 {
                isEmpty = false
            }else {
                break
            }
            result.append(String(Character(Unicode.Scalar(buffer[i]))))
        }
        buffer.removeAll()
        if isEmpty {
            return nil
        }
        
        
        return result
    }
    
    func clientConnectAsync(otherPort: Int, otherIp: String) -> Bool {
        do { //TODO async retry to connect to other
            client = try Socket(.inet, type: .stream, protocol: .tcp) // create client for sending data

            //try client?.connect(address: SocketAddress(port: Port(otherPort), address: otherIp)) // start trying to connect to p2p other server
            //try to connect to server
            print(prefix + " Tries to connect to other peer")
            try client?.connect(port: Port(otherPort), address: otherIp)
            print(prefix + "Reciever could connect to the other peer. Now able to retrieve MSG")
            return true
        } catch {
            print(prefix + "Client could not connect to other server: \(error)") //print the reason why the connection was not successful
        }
        client?.close() // client did not connect. Close pipe!!
        do {
            Thread.sleep(forTimeInterval: 1)
            //try await Task.sleep(nanoseconds: UInt64(0.5/*SECOND(S)*/ * Double(NSEC_PER_SEC))) //waites for X sec bec otherwise the console would be flooded
        } catch {
            print("Error sleeping \(error)")
        }
        return clientConnectAsync(otherPort: otherPort, otherIp: otherIp) //retry bec no connection could be etablished
    }
    
}

Sender.swift

import Foundation
import SocketSwift

class Sender { //AKA SERVER for SENDING messages (I know its confusing)
    var server: Socket? = nil //on this channel I will accept connections
    var send: Socket?
    
    init(serverPort: Int, ownIp: String) {
        do {
            server = try Socket(.inet, type: .stream, protocol: .tcp) //Initialize Server, this is running all time.
            try server?.set(option: .reuseAddress, true) // set SO_REUSEADDR to 1
            try server?.bind(port: Port(serverPort), address: ownIp) // bind 'ownIpt:serverPort'
            try server?.listen() // allow incoming connections
            print("Server on port \(serverPort)")
            
        } catch {
            print("Server creation failed: \(error)")
            
            return
        }
    }
        
    
    //Send message
    public func writeStream(message: String) throws {
        if send == nil {
            
            return
        }
        let inputSt: [UInt8] = ([UInt8])(message.utf8)
        
        do {
            try send?.write(inputSt)
        } catch let error {
            print("Error while sending message \(error)")
        }
        
        print("Message: \(message) should be printed")
    }
    
    func acceptClient() -> Socket? {
        
        do {
            print("trying to accept Peerconnection")
            
            send = try server?.accept()
            print("PEER connected to this server. Now able to send MSG")
        } catch {
            print("Error fetching connection \(error)")
            return nil
        }
        if send == nil {
            print("Peer failed to connected")
            return nil
        } else {
            
            //print("Someone connected \(String(describing:send.))")
            
            /*if send?.fileDescriptor == 5 {
                print("Du kannst nur empfangen")
                //send = try server?.accept()

            }else {
                print("Du kannst nur senden")
            }
            print("Someone connected \(String(describing: send?.fileDescriptor))")*/
            return send
        }
    }
}
2
  • 3
    As a general rule, anything that “spins” on a thread (with while true { } being the extreme example) is an antipattern. That’s just going to block the current thread. Anything that spins constantly should be scrupulously avoided. Generally, we’d want to shift to event-driven patterns. And, nowadays, we would want to use Swift concurrency patterns. Commented Mar 10, 2024 at 16:49
  • 1
    I might suggest checking out Building a custom peer-to-peer protocol sample code and Build device-to-device interactions with Network Framework video for examples of event-driven P2P. Commented Mar 10, 2024 at 17:31

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.