func send(_ payload: Data) {
connection!.send(content: payload, completion: .contentProcessed({ sendError in
if let error = sendError {
NSLog("Unable to process and send the data: \(error)")
} else {
NSLog("Data has been sent")
connection!.receiveMessage { (data, context, isComplete, error) in
if(isComplete){
guard let myData = data else { return }
NSLog("Received message: " + String(decoding: myData, as: UTF8.self))
}else{
NSLog("XYITA")
}
}
}
}))
}
So, I got this send function, connection works fine, connection.send works fine, but connection.receiveMessage throws strange error, which I cannot find how to resolve.
Error:
[connection] nw_socket_get_input_frames [C1:1] recvmsg(fd 17, 9216 bytes) [61: Connection refused]
Any suggestions?
Related
I simply wants to pass a string from one phone to another (vice versa) using TCP connection. Hence, I have a few questions as I'm a bit confused.
Can this be achieved using two different simulators in two different mac machines ?
Can this be achieved using two different simulators in the same mac machine ?
If this can be done on simulators would replacing the IP of the mac would work with 8080 port ?
My partially completed code as bellow;
class NWTCPConnection: NSObject {
var connection: NWConnection!
func connectToTcp() {
let PORT: NWEndpoint.Port = 8080
let ipAddress :NWEndpoint.Host = "192.168.8.133" //Machines IP
let queue = DispatchQueue(label: "TCP Client Queue")
let tcp = NWProtocolTCP.Options.init()
tcp.noDelay = true
let params = NWParameters.init(tls: nil, tcp: tcp)
connection = NWConnection(to: NWEndpoint.hostPort(host: ipAddress, port: PORT), using: params)
connection.stateUpdateHandler = { (newState) in
switch (newState) {
case .ready:
print("Socket State: Ready")
UserDefaults.standard.set(true, forKey: "isConnected")
self.sendMSG()
self.receive()
default:
UserDefaults.standard.set(false, forKey: "isConnected")
break
}
}
connection.start(queue: queue)
}
func sendMSG() {
print("send data")
let message1 = "hello world"
let content: Data = message1.data(using: .utf8)!
connection.send(content: content, completion: NWConnection.SendCompletion.contentProcessed(({ (NWError) in
if (NWError == nil) {
print("Data was sent to TCP destination ")
} else {
print("ERROR! Error when data (Type: Data) sending. NWError: \n \(NWError!)")
}
})))
}
// How to trigger this ???
func receive() {
connection.receiveMessage { (data, context, isComplete, error) in
if (isComplete) {
print("Receive is complete, count bytes: \(data!.count)")
if (data != nil) {
print(data!)
} else {
print("Data == nil")
}
}
}
}
the moment I run the simulator and call the connectToTcp() I get the following error
nw_socket_handle_socket_event [C1:1] Socket SO_ERROR [61: Connection refused]
I try to connect with Discord using IPC, but whatever i try, the error message stays the same Optional("\u{02}\0\0\0(\0\0\0{"code":1003,"message":"protocol error"}")
I started with the encode function, but that is UInt8 because Swift apparently does not support an UInt32 data object.
Then i tried to create an UInt32 (memory) array, to convert that to Data, that failed as well.
can someone point me into the direction where I make a mistake.
import Foundation
import Cocoa
import Network
class Discord {
enum opcode: UInt32 {
case handshake = 0
case frame = 1
case close = 2
case ping = 3
case pong = 4
}
var appID: String
private var connection: NWConnection?
private let endpoint: String = NSTemporaryDirectory() + "discord-ipc-0"
init(appID: String) {
self.appID = appID
}
func connect() {
print("Connecting to \(endpoint)")
connection = NWConnection(
to: NWEndpoint.unix(path: endpoint),
using: .tcp
)
connection?.stateUpdateHandler = { state in
switch state {
case .setup:
print("Setting up...")
case .preparing:
print("Prepairing...")
case .waiting(let error):
print("Waiting: \(error)")
case .ready:
print("Ready...")
case .failed(let error):
print("Failed: \(error)")
case .cancelled:
print("Cancelled :'(")
default:
break
}
}
connection?.receiveMessage { completeContent, contentContext, isComplete, error in
print(
String(data: completeContent ?? Data(), encoding: .utf8),
error
)
}
connection?.start(queue: .global())
}
func uint32encode(opcode: opcode, message string: String) -> Data {
let payload = string.data(using: .utf8)!
var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 8 + payload.count, alignment: 0)
defer { buffer.deallocate() }
buffer.copyBytes(from: payload)
buffer[8...] = buffer[..<payload.count]
buffer.storeBytes(of: opcode.rawValue, as: UInt32.self)
buffer.storeBytes(of: UInt32(payload.count), toByteOffset: 4, as: UInt32.self)
let uIntData = Data(bytes: &buffer, count: 8 + payload.count)
return uIntData
}
func encode(opcode: opcode, message string: String) -> Data {
let jsondata = string.data(using: .utf8)!
var data = Data()
data.append(UInt8(opcode.rawValue))
data.append(UInt8(jsondata.count))
data.append(contentsOf: [UInt8](jsondata))
/*
uint32 opcode (0 or 1)
uint32 length (length)
byte[length] jsonData (??)
*/
return data
}
func handshake() {
connect()
// We should say "hello", with opcode handshake
let hello = encode(opcode: .handshake, message: "{\"v\":1,\"client_id\":\"\(appID)\"}")
print("Sending \(String.init(data: hello, encoding: .utf8))")
connection?.send(
content: hello,
completion: .contentProcessed({ error in
print("Error:", error?.localizedDescription)
})
)
}
func handshakev2() {
connect()
// We should say "hello", with opcode handshake
let hello = uint32encode(opcode: .handshake, message: "{\"v\":1,\"client_id\":\"\(appID)\"}")
print("Sending (V2) \(String.init(data: hello, encoding: .utf8))")
connection?.send(
content: hello,
completion: .contentProcessed({ error in
print("Error (V2):", error?.localizedDescription)
})
)
}
}
I want to do TCP communication using a library called SwiftSocket.
Below is the sample code of SwiftSocket.
func echoService(client: TCPClient) {
print("Newclient from:\(client.address)[\(client.port)]")
var d = client.read(1024*10)
client.send(data: d!)
client.close()
}
func testServer() {
let server = TCPServer(address: "127.0.0.1", port: 8080)
switch server.listen() {
case .success:
while true {
if var client = server.accept() {
echoService(client: client)
} else {
print("accept error")
}
}
case .failure(let error):
print(error)
}
}
I want to convert the received message to String in the third line of the above code
var d = client.read(1024*10)
How can I do that?
Try this;
if let string = String(bytes: d, encoding: .utf8)
{
print(string)
} else
{
print("not a valid UTF-8 sequence")
}
Here is my socket io swift language code
and main.js file code also here
I have not properly idea why is not with socket io server.
let manager = SocketManager(socketURL: URL(string: "http://localhost:3000")!, config: [.log(true), .compress])
self.socket = manager.socket(forNamespace: "/")
establishSocketConnection()
func establishSocketConnection() {
self.socket.connect()
self.socket.on("connection") { ( dataArray, ack) -> Void in
print("connected to external server")
}
}
func cloesSocketConnection() {
self.socket.disconnect()
}
log:
2019-03-27 23:38:36.228040+0530 scoket[1693:38288] LOG SocketIOClient{/}: Handling event: statusChange with data: [connecting, 2]
2019-03-27 23:38:36.228241+0530 scoket[1693:38288] LOG SocketIOClient{/}: Joining namespace /
2019-03-27 23:38:36.228353+0530 scoket[1693:38288] LOG SocketManager: Tried connecting socket when engine isn't open. Connecting
2019-03-27 23:38:36.228437+0530 scoket[1693:38288] LOG SocketManager: Adding engine
2019-03-27 23:38:36.229083+0530 scoket[1693:38288] LOG SocketIOClient{/}: Adding handler for event: connection
2019-03-27 23:38:36.229115+0530 scoket[1693:38343] LOG SocketEngine: Starting engine. Server: http://localhost:3000
2019-03-27 23:38:36.229203+0530 scoket[1693:38343] LOG SocketEngine: Handshaking
2019-03-27 23:38:36.229239+0530 scoket[1693:38288] LOG SocketManager: Manager is being released
2019-03-27 23:38:36.232066+0530 scoket[1693:38343] LOG SocketEnginePolling: Doing polling GET http://localhost:3000/socket.io/?transport=polling&b64=1
2019-03-27 23:38:36.331457+0530 scoket[1693:38346] LOG SocketEnginePolling: Got polling response
2019-03-27 23:38:36.331618+0530 scoket[1693:38346] LOG SocketEnginePolling: Got poll message: 96:0{"sid":"yaMqmjKGkhok6TuqAAAC","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000}2:40
2019-03-27 23:38:36.331884+0530 scoket[1693:38346] LOG SocketEngine: Got message: 0{"sid":"yaMqmjKGkhok6TuqAAAC","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000}
2019-03-27 23:38:36.341490+0530 scoket[1693:38346] LOG SocketEngine: Got message: 40
2019-03-27 23:38:36.341726+0530 scoket[1693:38346] LOG SocketEngine: Writing poll: has data: false
2019-03-27 23:38:36.342051+0530 scoket[1693:38346] LOG SocketEnginePolling: Sending poll: as type: 2
2019-03-27 23:38:36.342505+0530 scoket[1693:38346] LOG SocketEnginePolling: Created POST string: 1:2
2019-03-27 23:38:36.342910+0530 scoket[1693:38346] LOG SocketEnginePolling: POSTing
2019-03-27 23:38:36.343202+0530 scoket[1693:38346] LOG SocketEngine: Engine is being released
your socket property it isn't true
your connection method must be like this:
func establishSocketConnection() {
let socket = manager.defaultSocket
self.socket.on("connection") { ( dataArray, ack) -> Void in
print("connected to external server")
}
}
and every time you want to create handler in socket (like socket.on or socket.emit)
you must create socket variable again.
hope to this help you.
Here is the latest swift 4.2 code
Connect with socket io server and get data in xcode
func ConnectToSocket() {
manager = SocketManager(socketURL: URL(string: "http://localhost:3000")!, config: [.log(true), .compress])
socketIOClient = manager.defaultSocket
socketIOClient.on(clientEvent: .connect) {data, ack in
print(data)
print("socket connected")
self.socketIOClient.emit("GetData", "dad")
}
socketIOClient.on("newChatMessage") { (dataArray, socketAck) -> Void in
print(dataArray)
}
socketIOClient.on(clientEvent: .error) { (data, eck) in
print(data)
print("socket error")
}
socketIOClient.on(clientEvent: .disconnect) { (data, eck) in
print(data)
print("socket disconnect")
}
socketIOClient.on(clientEvent: SocketClientEvent.reconnect) { (data, eck) in
print(data)
print("socket reconnect")
}
socketIOClient.connect()
}
Use this SocketIOManger for communicate with socket and make changes according to your need.
class SocketIOManager: NSObject {
static let sharedInstance = SocketIOManager()
var manager : SocketManager?
var socket : SocketIOClient?
override init() {
super.init()
}
/**
Create socket connection.
- parameter completionHandler : Called when complition will occure.
- parameter connected : True when socket connected.
- returns: nil
*/
func createSocketConnection (completionHandler: #escaping (_ connected: Bool) -> Void) {
let token = UserDefaults.standard.string(forKey: ConstantsBroadcast.Access_Token)!
manager = SocketManager(socketURL: URL(string: ConstantsBroadcast.socketBaseUrl)!
,config: [.log(true), .connectParams(["token": token]) ])
socket = manager?.defaultSocket
socket?.on(clientEvent: .connect) { data, ack in
print("socket connected.")
completionHandler(true)
}
socket?.connect()
}
/**
Disconnect socket.
*/
func closeConnection() {
socket?.disconnect()
}
/**
Add new user to socket.
- parameter username: current user name.
- parameter userid: current user id.
- parameter image: current user profile image url.
- returns: nil
*/
func addUserToServer(username: String, userid: String, image: String) {
let dict = ["username" : username, "userId": userid, "profileImage":image] as [String : Any]
self.socket?.emit("adduser", dict) //adduser
}
/**
Add handler for total connected user.
- parameter completionHandler : Called when complition will occure.
- parameter userCount : Total number of connected users.
- returns: nil
*/
func userConnectionHandlers(completionHandler: #escaping (_ userCount: String) -> Void) {
socket?.on("updateconnecteduser") { data,ack in //updateconnecteduser
debugPrint("connected user : ",data)
if let snippet = data[0] as? NSDictionary {
completionHandler("\(String(describing: snippet.value(forKey: "viewers")!))")
}
}
}
/**
Send new message.
- parameter message: user text message.
- returns: nil
*/
func sendMessage(message :String){
if socket?.status == .connected {
self.socket?.emit("sendchat", ["message": message]) //sendchat
}
else{
print("socket not connected")
}
}
/**
Add handler for get new messages.
- parameter completionHandler : Called when complition will occure.
- parameter messageInfo : New message data.
- returns: nil
*/
func newMessageHandlers(completionHandler: #escaping (_ messageInfo: ChatItemModel) -> Void) {
socket?.on("updatechat") { data,ack in //updatechat
print(data)
var msgData = ChatItemModel()
if let chatData = data[0] as? NSDictionary {
if let mId = chatData.value(forKey: "chatCommentId") as? String{
msgData.ChatCommentId = mId
}
if let userId = chatData.value(forKey: "userId") as? String {
msgData.UserID = userId
}
if let username = chatData.value(forKey: "username") as? String{
msgData.UserName = username
}
if let image = chatData.value(forKey: "profileImage") as? String{
msgData.ProfileImage = image
}
if let message = chatData.value(forKey: "message") as? String{
msgData.Message = message
}
if let createdAt = chatData.value(forKey: "createdAt") as? String{
msgData.CreatedAT = createdAt
}
completionHandler(msgData)
}
}
}
/**
Block user.
- parameter userId: user id.
- returns: nil
*/
func blockUser(userId : String){
if socket?.status == .connected {
self.socket?.emit("blockuser", ["userId" : userId]) //blockuser
print("blockuser emmited : ", userId)
}
else{
print("socket not connected")
}
}
/**
Add handler for block user.
- parameter completionHandler : Called when complition will occure.
- parameter userId : Blocked user id.
- returns: nil
*/
func blockUserHandler(completionHandler: #escaping (_ status : Int, _ userId: String) -> Void) {
socket?.on("updateblockeduser") { data,ack in //updateblockeduser
print("blcked userId : ",data)
if let blockedItem = data[0] as? NSDictionary {
if let status = blockedItem.value(forKey: "status") as? Int{
if let userId = blockedItem.value(forKey: "userId") as? String{
completionHandler(status, userId)
}
}
}
}
}
}
At the moment, Users will get a "No internet connection" error, when the cloudfunctions API to get the Twilio token is offline or faulty. This should return a different error message. how do i refine the error message according to the kind of error encountered in swift?
class Token {
let value: String
init (url: String = "userTokenURL") throws {
guard let requestURL = URL(string: url) else {
throw Token.Error.invalidURL
}
do {
let data = try Data(contentsOf: requestURL)
guard let stringToken = String(data: data, encoding: .utf8) else {
throw Token.Error.couldNotConvertDataToString
}
value = stringToken
} catch let error as NSError {
print ("Error fetching token data, \(error)")
throw Token.Error.noInternet
}
}
}
extension Token {
enum Error: Swift.Error {
case invalidURL
case couldNotConvertDataToString
case noInternet
var description: String? {
switch self {
case .invalidURL:
return NSLocalizedString("Token URL is invalid.", comment: "")
case .couldNotConvertDataToString:
return NSLocalizedString("Token Data could not be converted to String.", comment: "")
case .noInternet:
return NSLocalizedString("Internet connection failed.", comment: "")
}
}
}
}