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!

5
  • 2
    Have you looked at developer.apple.com/library/mac/documentation/Cocoa/Conceptual/… ? Commented Jul 21, 2014 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 Commented Jul 21, 2014 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... Commented Jul 21, 2014 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. Commented Jul 21, 2014 at 19:48
  • anything new @Grimxn ? Commented Jul 23, 2014 at 21:20

1 Answer 1

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)

Sign up to request clarification or add additional context in comments.

3 Comments

Note that getStreamsToHost(_:port:inputStream:outputStream:) is deprecated. Use getStreamsToHostWithName("127.0.0.1", port: port, inputStream: &inp, outputStream: &out) instead.
The above comment's suggestion does not exist anymore. Use Stream.getStreamsToHost(withName: address, port: port, inputStream: &inp, outputStream: &out)
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.