11

If I wanted to connect to a server, in Java I would open a Socket and initialize it with port and host address, then retrieve the input/output streams and read/write whatever I want.

In Swift I'm having hard time doing so since it's not built that way and I would really like to see a simple example of how to connect to a server, retrieve the streams and use them.

EDIT1:

This is the tested code after what @Grimxn referenced.

var host = "http://google.com"
var readStream :CFReadStreamRef
var writeStream :CFWriteSteamRef
var socket = CFStreamCreatePairWithSocketToHost(nil, host, 80, readStream, writeStream)

Main issues:

  1. Initializing the two streams above also require the use of CFAllocator which I know nothing about. Using kCFAllocatorDefault did not quite help, same errors.

  2. The above code returns this error: Cannot Convert the expression's type 'Void' to type UInt32.

  3. When I construct a UInt32 using UInt32(80) for example, the error is: Could not find an overload for 'init' that accepts the supplied argument.

I appreciate any help!

johni
  • 5,342
  • 6
  • 42
  • 70
  • 2
    Have you looked at https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Streams/Articles/NetworkStreams.html ? – Grimxn Jul 21 '14 at 11:10
  • 1
    Yeah, I did. I have problem using CFStreamCreatePairWithSocketToHost. For this simple code I get this error Cannot Convert the expression's type 'Void' to type UInt32. It also happens when I init a UInt32 object with '80' as argument. in that case, the error is: Could not find an overload for 'init' that accepts the supplied argument. `var host = "google.com"` `var readStream :CFReadStreamRef` `var writeStream :CFWriteStreamRef` `var socket = CFStreamCreatePairWithSocketToHost(nil, host, 80, readStream, writeStream)` **1 simple example in swift will solve me many issues** – johni Jul 21 '14 at 19:47
  • Can you post what you've tried? It's easier for folk to work on actual code, rather than guess what you might have done... – Grimxn Jul 21 '14 at 19:47
  • Of course, I have just edited the comment I had a problem making it look right instead of a mess. Thanks for helping so much. – johni Jul 21 '14 at 19:48
  • anything new @Grimxn ? – johni Jul 23 '14 at 21:20

1 Answers1

29

I have figured it myself, for those who look for an explanation read ahead;

There are multiple ways of using Sockets to communicate with local application or a remote server.

The problem described in the original post was to get the Input/Output streams and get them to work. (At the end of this post there's a reference to another post of mine explaining how to use those streams)

The NSStream class has a static method (class function in swift) called getStreamsToHost. All you have to prepare is a NSHost objected initialized with a real host address, a port number, a reference to a NSInputStream obj and also for a NSOutputStream obj. Then, you can use the streams as shown here and explained in the reference post.

look at this simple code;

let addr = "127.0.0.1"
let port = 4000

var host :NSHost = NSHost(address: addr)
var inp :NSInputStream?
var out :NSOutputStream?

NSStream.getStreamsToHost(host, port: port, inputStream: &inp, outputStream: &out)

let inputStream = inp!
let outputStream = out!
inputStream.open()
outputStream.open()

var readByte :UInt8 = 0
while inputStream.hasBytesAvailable {
    inputStream.read(&readByte, maxLength: 1)
}

// buffer is a UInt8 array containing bytes of the string "Jonathan Yaniv.".
outputStream.write(&buffer, maxLength: buffer.count)

Before executing this simple code, I launched ncat to listen on port 4000 in my terminal and typed "Hello !" and left the socket opened for communication.

Jonathans-MacBook-Air:~ johni$ ncat -l 4000
Hello !
Jonathan Yaniv.
Jonathans-MacBook-Air:~ johni$ 

After launching the code, you can see that I have received the string "Jonathan Yaniv.\n" to the terminal before the socket was closed.

I hope this saved some headache to some of you. If you have more questions give it a shot, I hope I'll be able to answer it.

The & notation is explained in this post. (Reference to NSInputStream read use)

Community
  • 1
  • 1
johni
  • 5,342
  • 6
  • 42
  • 70
  • 4
    Note that getStreamsToHost(_:port:inputStream:outputStream:) is deprecated. Use getStreamsToHostWithName("127.0.0.1", port: port, inputStream: &inp, outputStream: &out) instead. – aust Aug 26 '15 at 15:34
  • 1
    The above comment's suggestion does not exist anymore. Use Stream.getStreamsToHost(withName: address, port: port, inputStream: &inp, outputStream: &out) – Massimo Nov 29 '16 at 14:24
  • I am confused (and a total Swift newbie). Neither "NSStream.getStreamsToHost", "Stream.getStreamsToHost", nor "Stream.getStreamsToHost" work for me. I am using Swift 4.0.3. – Frans Lundberg Jan 12 '18 at 09:59