how to create a socket in swift that listen to and write on it? Is GCDAsyncSocket a right way or another way is possible? I used CFStreamCreatePairWithSocketToHost to connect to socket but can not read data from.
First, we need to create a Socket class: Create a class (I called it SocketServer), this class is going to connect to the desired socket using host & port . Later on, we're going to declare a protocol ( SocketDelegate ) that this class calls its methods when InputStream has available response.
The connect() call on a stream socket is used by the client application to establish a connection to a server. The server must have a passive open pending. A server that is using sockets must successfully call bind() and listen() before a connection can be accepted by the server with accept().
The socket communication relies on the client-server logic, where a persistent connection between a server and a client always exists. To be more precise, the server “opens” a dedicated port where clients get connected to it.
For those who are interested for a Swift 3 implementation. It's referenced heavily from raywenderlich's example with some edits.
func connect() {
Stream.getStreamsToHost(withName: self.address!, port: self.port!, inputStream: &self.inputStream, outputStream: &self.outputStream);
guard let _ = inputStream, let _ = outputStream else {
// your own execption or otherwise
return;
}
self.inputStream?.delegate = self;
self.outputStream?.delegate = self;
self.inputStream?.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode);
self.outputStream?.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode);
self.inputStream?.open();
self.outputStream?.open();
}
func disconnect() {
if let stream = self.inputStream {
stream.close();
stream.remove(from: RunLoop.current, forMode: RunLoopMode.commonModes);
}
if let stream = self.outputStream {
stream.close();
stream.remove(from: RunLoop.current, forMode: RunLoopMode.commonModes);
}
self.inputStream = nil;
self.outputStream = nil;
}
func write(data:Data) {
let _ = data.withUnsafeBytes { (unsafePointer:UnsafePointer<UInt8>) in
let bytesWritten = self.outputStream?.write(unsafePointer, maxLength: data.count);
};
}
func readAvailableBytes(stream: InputStream) {
var buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: maxReadLength);
while stream.hasBytesAvailable {
let numberOfBytesRead = stream.read(buffer, maxLength: maxReadLength)
if numberOfBytesRead < 0 {
if let _ = stream.streamError {
break
}
}
//Construct the Message object
if(numberOfBytesRead > 0){
let output = String(cString:buffer)
NSLog("server said: %@", output)
} else {
NSLog("empty string from stream")
}
}
buffer.deallocate(capacity: maxReadLength);
}
And be sure to implement StreamDelegate and the delegate method in your handling class:
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
NSLog("Receieve stream event: %d", eventCode.rawValue);
switch (eventCode){
case Stream.Event.errorOccurred:
NSLog("ErrorOccurred")
break;
case Stream.Event.endEncountered:
NSLog("EndEncountered")
break;
case Stream.Event.hasBytesAvailable:
NSLog("HasBytesAvaible");
break;
case Stream.Event.openCompleted:
NSLog("OpenCompleted");
break;
case Stream.Event.hasSpaceAvailable:
NSLog("HasSpaceAvailable");
break;
default:
NSLog("default reached. unknown stream event")
break;
}
}
Note: There are some changes from raywnderlich's implementation, particularly in the delegate method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With