I have following function for connecting to a TCP Socket (Server on a Raspberry Pi, which I directly connect to via Access Point)
func connect (host: String, port: Int) {
Stream.getStreamsToHost(withName: addr, port: port, inputStream: &inputStream, outputStream: &outputStream)
if outputStream != nil && inputStream != nil {
outputStream!.delegate = self
inputStream!.delegate = self
outputStream!.schedule(in: .main, forMode: RunLoopMode.defaultRunLoopMode)
inputStream!.schedule(in: .main, forMode: RunLoopMode.defaultRunLoopMode)
outputStream!.open()
inputStream!.open()
}
}
When I'm connected to the Wifi-Hotspot of the Raspberry Pi following delegate method gets called and I can start writing data:
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
if aStream === inputStream {
switch eventCode {
case Stream.Event.errorOccurred:
print("input: ErrorOccurred: \(aStream.streamError?.localizedDescription)")
self.Label.text = "Disconnected"
case Stream.Event.openCompleted:
print("input: OpenCompleted")
case Stream.Event.hasBytesAvailable:
print("input: HasBytesAvailable")
// Here you can `read()` from `inputStream`
default:
break
}
}
else if aStream === outputStream {
switch eventCode {
case Stream.Event.errorOccurred:
print("output: ErrorOccurred: \(aStream.streamError?.localizedDescription)")
self.Label.text = "Disconnected"
case Stream.Event.openCompleted:
print("output: OpenCompleted")
case Stream.Event.hasSpaceAvailable:
// print("output: HasSpaceAvailable")
// Here you can write() to `outputStream`
self.write(f: l)
self.write(f: r)
default:
break
}
}
}
But when I'm connected to another WiFi this method doesn't get called.
How can I detect that this method didn't get called, so I can alert the user that he isn't connected and that he should try connecting again?
Related
I'm sending some data through UDP but the receiveMessage(completion:) doesn't get invoked.
With Network Framework i open the connection and when it's in the ready state i send a single datagram which is being sent successfully but i have problem receiving the incoming datagram.
I call receive on the same connection by the way.
class func connect()
{
connection = NWConnection(host: hostUDP, port: portUDP, using: .udp)
connection?.stateUpdateHandler =
{
(newState) in switch (newState)
{
case .ready:
//The connection is established and ready to send and recieve data.
print("ready")
self.sendPaket(self.sendingPacket)
self.receive()
print("i read this line")
case .setup:
//The connection has been initialized but not started
print("setup")
case .cancelled:
//The connection has been cancelled
print("cancelled")
case .preparing:
//The connection in the process of being established
print("Preparing")
default:
//The connection has disconnected or encountered an error
print("waiting or failed")
}
}
connection?.start(queue: .global())
}
class func sendPaket(_ packet:String)
{
let packet = dataWithHexString(hex: sendingPacket)
print("converted version to byte is :\(packet)")
connection?.send(content: packet, completion: NWConnection.SendCompletion.contentProcessed((
{
(NWError) in
if (NWError != nil)
{
print("error in sending packet : \(NWError!)")
}else
{
print("Packet Sent Successfully")
}
})))
}
class func receive()
{
print("Receive func got called")
connection?.receive(minimumIncompleteLength: 17, maximumLength: 100, completion:(
{
(data, context, isComplete, error) in
print(context!)
print("receiveMessage called")
if (isComplete)
{
print("receiving is complete!")
if (data != nil)
{
let backToString = String(decoding: data!, as: UTF8.self)
print("Received message: \(backToString)")
}else
{
print("data is nil")
}
}else
{
print("isn't complete")
}
if error != nil
{
print("error in receiving : \(error!)")
}
}))
}
What should i do?
I am trying to create a connection to web socket with a link ws://link.net:8888/ws?token= to open communication with the server.
I found out that I could use Stream but I don't know how to add access_token to the end.
Stream.getStreamsToHost(withName: host, port: port, inputStream: &inputStream, outputStream: &outputStream)
if inputStream != nil && outputStream != nil {
// Set delegate
inputStream!.delegate = self
outputStream!.delegate = self
// Schedule
inputStream!.schedule(in: .main, forMode: RunLoopMode.defaultRunLoopMode)
outputStream!.schedule(in: .main, forMode: RunLoopMode.defaultRunLoopMode)
print("Start open()")
// Open!
inputStream!.open()
outputStream!.open()
}
And for some reason even if I try to connect to link without access key, I am unsuccessful. So does anyone have a way how to open connection to the socket with access_key added I would be very grateful?
I also tried https://github.com/swiftsocket/SwiftSocket but it also doesn't have an option to add anything on end, the only thing I will try now it is https://github.com/socketio/socket.io-client-swift.
EDIT1:
So after a comment from Dan Karbayev I checked out Starscream with code
let url = "ws://link.net:5000/ws?token=token"
let socket = WebSocket(url: URL(string: url)!)
socket.onConnect = {
print("websocket is connected")
}
//websocketDidDisconnect
socket.onDisconnect = { (error: Error?) in
print("websocket is disconnected: \
(error?.localizedDescription)")
}
//websocketDidReceiveMessage
socket.onText = { (text: String) in
print("got some text: \(text)")
}
//websocketDidReceiveData
socket.onData = { (data: Data) in
print("got some data: \(data.count)")
}
//you could do onPong as well.
socket.connect()
But for some odd reason none of socket methods don't wake up.
EDIT 2:
At the end I ended using https://github.com/tidwall/SwiftWebSocket.
It worked right away.
But thanks to all for help.
I want to communicate two iOS devices in local area network via socket.
Right now, I am able to communicate with web socket by writing a client side code in iOS, but i want to know there is any way to communicate two iOS devises via socket, so one iOS device work as server and other iOS device work as a client.
For Client side i am using below code:
// MARK:- communication initilaize Methode.
func initNetworkCommunication() {
//Initilize network communication.
host = "192.168.2.15" //Server IP
port = 8788 //Port for communication
Stream.getStreamsToHost(withName: host!, port: port!, inputStream: &inputstream, outputStream: &outputstream)
if ((inputstream != nil) && (outputstream != nil)) {
// connection not failed.
print("Connection to \(host!):\(port!)")
inputstream?.delegate = self
outputstream?.delegate = self
inputstream?.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)
outputstream?.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)
inputstream?.open()
outputstream?.open()
}
}
And for handling a connection, implement a delegate of StreamDelegate as:
// MARK:- StreamDelegate Methods.
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
switch eventCode {
case Stream.Event.openCompleted:
print("Connected")
//Make connection connect.
outputstream_Status = true
break
case Stream.Event.hasBytesAvailable:
break
case Stream.Event.hasSpaceAvailable:
break
case Stream.Event.endEncountered:
print("Connection closed by the server.")
//Make connection disconnect.
outputstream_Status = false
//De-Initialize the Stream.
closeNetworkCommunication()
break
case Stream.Event.errorOccurred:
print("Can not connect to the host!")
//Make connection disconnect.
outputstream_Status = false
break
default:
break
}
}
}
So I was playing around with sockets in Swift and trying to connect the app with my server. I was having the app connect to the IP address of the server and used netcat on the server for testing. During execution, the console output from the app showed it had successfully connected to the server. However, the stream delegate does not seem to be responsive. When I typed into netcat, the app console did not print anything. I have searched for quite a while and found that my implementation is pretty similar to others. Perhaps I am missing something here that I do not see.
Any thought to this problem would be greatly appreciated!
Code is attached below:
import UIKit
class ViewController: UIViewController, StreamDelegate {
let addr:String = "52.34.56.78"
let port:Int = 1234
var inputStream: InputStream?
var outputStream: OutputStream?
override func viewDidLoad() {
super.viewDidLoad()
self.connect(host: addr, port: port)
}
func connect(host: String, port: Int) {
Stream.getStreamsToHost(withName: host, port: port, inputStream: &inputStream, outputStream: &outputStream)
if inputStream != nil && outputStream != nil {
inputStream!.delegate = self
outputStream!.delegate = self
inputStream!.schedule(in: RunLoop.main, forMode: RunLoopMode.defaultRunLoopMode)
outputStream!.schedule(in: RunLoop.main, forMode: RunLoopMode.defaultRunLoopMode)
inputStream!.open()
outputStream!.open()
print("successfully connected")
}
else {
print("connection unsuccessful")
}
}
func stream(aStream: Stream, handleEvent eventCode: Stream.Event) {
if aStream === inputStream {
switch eventCode {
case Stream.Event.errorOccurred:
print("input: ErrorOccurred: \(aStream.streamError?.localizedDescription)")
break
case Stream.Event.openCompleted:
print("input: OpenCompleted")
break
case Stream.Event.hasBytesAvailable:
print("input: HasBytesAvailable")
break
default:
break
}
}
else {
print("unknown stuff happened")
}
}
}
So after a lot of trials and errors, I finally realized the stream() function did not work just because the signature of this function is incorrect/obsolete.
Here is what I was using:
func stream(aStream: Stream, handleEvent eventCode: Stream.Event)
But really it should be:
func stream(_ aStream: Stream, handle eventCode: Stream.Event)
This is likely a syntax conversion from previous Swift version to Swift 3. The XCode compiler usually detects obsolete functions/syntax, but sadly did not catch this one.
Hopefully my answer could help out those who are still suffering from this problem.
I have an issue with connecting to a Java socket with StreamDelegate in Swift 3. I am currently in the process of rewriting a big Objective C project where this piece of code runs like a charm, but I can't seem to be able to get it to work in Swift 3. The problem I am having is that the stream function never runs. So "Stream!" is never printed out. The Stream.Status after self.outputStream.open() is called is 1 (opening). The code runs without any problems and "Opening streams on thread:" gets called.
The socket I am trying to connect to is a Java socket.
Note: I have experienced that the debugger has printed out a message saying there is no handler attached, but I do not know it is related.
I have found a couple of similar posts, but not on this exact problem. If anyone has any ideas, I would be happy to hear them out! Thanks to anyone who tries to help.
import Foundation
#objc class SocketConnector : NSObject, StreamDelegate {
var inputStream : InputStream!
var outputStream : OutputStream!
var lock : NSRecursiveLock
override init () {
lock = NSRecursiveLock.init()
}
func connect (host : String, port : Int) -> Bool {
lock.lock()
var readStream : Unmanaged<CFReadStream>?
var writeStream : Unmanaged<CFWriteStream>?
CFStreamCreatePairWithSocketToHost(nil, host as CFString!, UInt32(port), &readStream, &writeStream)
inputStream = readStream!.takeRetainedValue()
outputStream = writeStream!.takeRetainedValue()
self.inputStream.delegate = self
self.outputStream.delegate = self
self.inputStream.schedule(in: RunLoop.current, forMode: .defaultRunLoopMode)
self.outputStream.schedule(in: RunLoop.current, forMode: .defaultRunLoopMode)
self.inputStream.open()
self.outputStream.open()
print("Opening streams on thread: %#", Thread.current)
lock.unlock()
return true
}
func stream (aStream : Stream, handleEvent eventCode : Stream.Event) {
print("Stream!")
switch eventCode {
case Stream.Event.hasBytesAvailable:
print("Stream has bytes:");
break;
case Stream.Event.errorOccurred:
print("Stream error occurred: %#",aStream.streamError?.localizedDescription)
case Stream.Event.openCompleted:
print("Stream has bytes:")
break
case Stream.Event.endEncountered:
print("Stream ended")
self.closeStreams()
break
default:
break
}
}
Your implement is not compatible with stream method of StreamDelegate.
You must change to this:
func stream(_ aStream: Stream, handle eventCode: Stream.Event)
instead of
func stream (aStream : Stream, handleEvent eventCode : Stream.Event