forked from Grimi94/SimpleSocket
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSocket.swift
More file actions
205 lines (166 loc) · 6.42 KB
/
Copy pathSocket.swift
File metadata and controls
205 lines (166 loc) · 6.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
//
// SocketManager.swift
//
//
// Created by Grimi on 6/21/15.
//
//
import UIKit
@objc protocol SocketStreamDelegate{
func socketDidConnect(stream:NSStream)
optional func socketDidDisconnet(stream:NSStream, message:String)
optional func socketDidReceiveMessage(stream:NSStream, message:String)
optional func socketDidEndConnection()
}
class Socket: NSObject, NSStreamDelegate {
var delegate:SocketStreamDelegate?
private let bufferSize = 1024
private var _host:String?
private var _port:Int?
private var _messagesQueue:Array<String> = [String]()
private var _streamHasSpace:Bool = false
private var inputStream: NSInputStream?
private var outputStream: NSOutputStream?
private var token: dispatch_once_t = 0
var isClosed = false
var isOpen = false
var host:String?{
get{
return self._host
}
}
var port:Int?{
get{
return self._port
}
}
deinit{
if let inputStr = self.inputStream{
inputStr.close()
inputStr.removeFromRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
}
if let outputStr = self.outputStream{
outputStr.close()
outputStr.removeFromRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
}
}
/**
Opens streaming for both reading and writing, error will be thrown if you try to send a message and streaming hasn't been opened
:param: host String with host portion
:param: port Port
*/
final func open(host:String!, port:Int!){
self._host = host
self._port = port
if #available(iOS 8.0, *) {
NSStream.getStreamsToHostWithName(self._host!, port: self._port!, inputStream: &inputStream, outputStream: &outputStream)
} else {
var inStreamUnmanaged:Unmanaged<CFReadStream>?
var outStreamUnmanaged:Unmanaged<CFWriteStream>?
CFStreamCreatePairWithSocketToHost(nil, host, UInt32(port), &inStreamUnmanaged, &outStreamUnmanaged)
inputStream = inStreamUnmanaged?.takeRetainedValue()
outputStream = outStreamUnmanaged?.takeRetainedValue()
}
if inputStream != nil && outputStream != nil {
inputStream!.delegate = self
outputStream!.delegate = self
inputStream!.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
outputStream!.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
print("[SCKT]: Open Stream")
self._messagesQueue = Array()
inputStream!.open()
outputStream!.open()
} else {
print("[SCKT]: Failed Getting Streams")
}
}
final func close(){
if let inputStr = self.inputStream{
inputStr.delegate = nil
inputStr.close()
inputStr.removeFromRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
}
if let outputStr = self.outputStream{
outputStr.delegate = nil
outputStr.close()
outputStr.removeFromRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
}
isClosed = true
}
/**
NSStream Delegate Method where we handle errors, read and write data from input and output streams
:param: stream NStream that called delegate method
:param: eventCode Event Code
*/
final func stream(stream: NSStream, handleEvent eventCode: NSStreamEvent) {
switch eventCode {
case NSStreamEvent.EndEncountered:
endEncountered(stream)
case NSStreamEvent.ErrorOccurred:
print("[SCKT]: ErrorOccurred: \(stream.streamError?.description)")
case NSStreamEvent.OpenCompleted:
openCompleted(stream)
case NSStreamEvent.HasBytesAvailable:
handleIncommingStream(stream)
case NSStreamEvent.HasSpaceAvailable:
print("space available")
writeToStream()
break;
default:
break;
}
}
final func endEncountered(stream:NSStream){
}
final func openCompleted(stream:NSStream){
if(self.inputStream?.streamStatus == .Open && self.outputStream?.streamStatus == .Open){
dispatch_once(&token) {
self.isOpen = true
self.delegate?.socketDidConnect(stream)
}
}
}
/**
Reads bytes asynchronously from incomming stream and calls delegate method socketDidReceiveMessage
:param: stream An NSInputStream
*/
final func handleIncommingStream(stream: NSStream){
if let inputStream = stream as? NSInputStream {
var buffer = Array<UInt8>(count: bufferSize, repeatedValue: 0)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
let bytesRead = inputStream.read(&buffer, maxLength: 1024)
if bytesRead >= 0 {
if let output = NSString(bytes: &buffer, length: bytesRead, encoding: NSUTF8StringEncoding){
self.delegate?.socketDidReceiveMessage!(stream, message: output as String)
}
} else {
// Handle error
}
})
} else {
print("[SCKT]: \(#function) : Incorrect stream received")
}
}
/**
If messages exist in _messagesQueue it will remove and it and send it, if there is an error
it will return the message to the queue
*/
final func writeToStream(){
if _messagesQueue.count > 0 && self.outputStream!.hasSpaceAvailable {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
let message = self._messagesQueue.removeLast()
let data: NSData = message.dataUsingEncoding(NSUTF8StringEncoding)!
var buffer = [UInt8](count:data.length, repeatedValue:0)
data.getBytes(&buffer, length:data.length * sizeof(UInt8))
//An error ocurred when writing
if self.outputStream!.write(&buffer, maxLength: data.length) == -1 {
self._messagesQueue.append(message)
}
})
}
}
final func send(message:String){
_messagesQueue.insert(message, atIndex: 0)
writeToStream()
}
}