Socket Up Mac OS

broken image


Article Category:#Code

  1. Socket Up Mac Os Catalina
  2. Mac Os Mojave
  3. Socket Up Mac Os X

If you are writing code for OS X and iOS exclusively, use POSIX networking calls to set up your network sockets. Then, use GCD or CFSocket to integrate the sockets into your run loop. Use pure POSIX networking code with a POSIX-based run loop ( select ) if cross-platform portability with non-Apple platforms is required. Next time you start a service on your Mac with OS X, and you're not sure what port it happens to run on, try sockstat. robg adds: To use this script, first copy the text from the view source link, and then switch to Terminal. Open a new file for editing somewhere on your command path (/usr/local/bin, your user's /bin, etc.).

Posted on

.

Updates

Hello. How are you? Thanks for stopping by.

It used to be tricky to get Docker working on OS X, which is why I wrote this here blog post. With the release of Docker 1.8, it just got way easier. Now there's a new thing, Docker Toolbox, that makes it super easy. You should install that instead of reading this post. Or you can read it if you want, I think it's a pretty good blog post and you'll learn some stuff. No pressure, though.

Have you heard of Docker? You probably have—everybody's talking about it. It's the new hotness. Even my dad's like, 'what's Docker? I saw someone twitter about it on the Facebook. You should call your mom.'

Docker is a program that makes running and managing containers super easy. It has the potential to change all aspects of server-side applications, from development and testing to deployment and scaling. It's pretty cool.

Recently, I've been working through The Docker Book. Escape (itch) (pislify) mac os. It's a top notch book and I highly recommend it, but I've had some problems running the examples on OS X. After a certain point, the book assumes you're using Linux and skips some of the extra configuration required to make the examples work on OS X. This isn't the book's fault; rather, it speaks to underlying issues with how Docker works on OS X.

This post is a walkthrough of the issues you'll face running Docker on OS X and the workarounds to deal with them. It's not meant to be a tutorial on Docker itself, but I encourage you to follow along and type in all the commands. You'll get a better understanding of how Docker works in general and on OS X specifically. Plus, if you decide to dig deeper into Docker on your Mac, you'll be saved hours of troubleshooting. Don't say I never gave you nothing.

First, let's talk about how Docker works and why running it on OS X no work so good.

How Docker Works

Docker is a client-server application. The Docker server is a daemon that does all the heavy lifting: building and downloading images, starting and stopping containers, and the like. It exposes a REST API for remote management.

The Docker client is a command line program that communicates with the Docker server using the REST API. You will interact with Docker by using the client to send commands to the server.

The machine running the Docker server is called the Docker host. The host can be any machine—your laptop, a server in the Cloud™, etc—but, because Docker uses features only available to Linux, that machine must be running Linux (more specifically, the Linux kernel).

Docker on Linux

Suppose we want to run containers directly on our Linux laptop. Here's how it looks:

Docking on Linux

The laptop is running both the client and the server, thus making it the Docker host. Easy.

Docker on OS X

Here's the thing about OS X: it's not Linux. It doesn't have the kernel features required to run Docker containers natively. We still need to have Linux running somewhere.

Enter boot2docker. boot2docker is a 'lightweight Linux distribution made specifically to run Docker containers.' Spoiler alert: you're going to run it in a VM on your Mac.

Here's a diagram of how we'll use boot2docker:

Docking on OS X

We'll run the Docker client natively on OS X, but the Docker server will run inside our boot2docker VM. This also means boot2docker, not OS X, is the Docker host, not OS X.

Make sense? Let's install dat software.

Installation

Step 1: Install VirtualBox

Go here and do it. You don't need my help with that.

Step 2: Install Docker and boot2docker

You have two choices: the offical package from the Docker site or homebrew. I prefer homebrew because I like to manage my environment from the command line. The choice is yours.

Step 3: Initialize and start boot2docker

First, we need to initialize boot2docker (we only have to do this once):

Next, we can start up the VM. Do like it says:

Step 4: Set the DOCKER_HOST environment variable

The Docker client assumes the Docker host is the current machine. We need to tell it to use our boot2docker VM by setting the DOCKER_HOST environment variable:

Your VM might have a different IP address—use whatever boot2docker up told you to use. You probably want to add that environment variable to your shell config.

Step 5: Profit

Let's test it out:

Great success. To recap: we've set up a VirtualBox VM running boot2docker. The VM runs the Docker server, and we're communicating with it using the Docker client on OS X.

Bueno. Let's do some containers.

Common Problems

We have a 'working' Docker installation. Let's see where it falls apart and how we can fix it.

Problem #1: Port Forwarding

The Problem: Docker forwards ports from the container to the host, which is boot2docker, not OS X.

Let's start a container running nginx:

This command starts a new container as a daemon (-d), automatically forwards the ports specified in the image (-P), gives it the name ‘web' (--name web), and uses the nginx image. Our new container has the unique identifier 0092c03e1eba...

Verify the container is running:

Under the PORTS heading, we can see our container exposes port 80, and Docker has forwarded this port from the container to a random port, 49153, on the host.

Let's curl our new site:

It didn't work. Why?

Remember, Docker is mapping port 80 to port 49153 on the Docker host. If we were on Linux, our Docker host would be localhost, but we aren't, so it's not. It's our VM.

The Solution: Use the VM's IP address.

boot2docker comes with a command to get the IP address of the VM:

Let's plug that into our curl command:

Success! Sort of. We got the web page, but we got The VM's Host only interface IP address is:, too. What's the deal with that nonsense.

Turns out, boot2docker ip outputs the IP address to standard output and The VM's Host only interface IP address is: to standard error. The $(boot2docker ip) subcommand captures standard output but not standard error, which still goes to the terminal. Scumbag boot2docker.

This is annoying. I am annoyed. Here's a bash function to fix it:

Stick that in your shell config, then use it like so:

Groovy. This gives us a reference for the IP address in the terminal, but it would be nice to have something similar for other apps, like the browser. Let's add a dockerhost entry to the /etc/hosts file:

Now we can use it everywhere:

Great success. Make sure to stop and remove the container before continuing:

VirtualBox assigns IP addresses using DHCP, meaning the IP address could change. If you're only using one VM, it should always get the same IP, but if you're VMing on the reg, it could change. Fair warning.

Bonus Alternate Solution: Forward all of Docker's ports from the VM to localhost.

If you really want to access your Docker containers via localhost, you can forward all of the ports in Docker's port range from the VM to localhost. Here's a bash script, taken from here, to do that:

By doing this, Docker will forward port 80 to, say, port 49153 on the VM, and VirtualBox will forward port 49153 from the VM to localhost. Soon, inception. You should really just use the VM's IP address mmkay.

Problem #2: Mounting Volumes

The Problem: Docker mounts volumes from the boot2docker VM, not from OS X.

Docker supports volumes: you can mount a directory from the host into your container. Volumes are one way to give your container access to resources in the outside world. For example, we could start an nginx container that serves files from the host using a volume. Let's try it out.

First, let's create a new directory and add an index.html:

(Make sure to replace /Users/Chris with your own path).

Next, we'll start another nginx container, this time mounting our new directory inside the container at nginx's web root:

We need the port number for port 80 on our container:

Let's try to curl our new page:

Well, that didn't work. The problem, again, is our VM. Docker is trying to mount /Users/Chris/web from the host into our container, but the host is boot2docker, not OS X. boot2docker doesn't know anything about files on OS X.

The Solution: Mount OS X's /Users directory into the VM.

By mounting /Users into our VM, boot2docker gains a /Users volume that points to the same directory on OS X. Referencing /Users/Chris/web inside boot2docker now points directly to /Users/Chris/web on OS X, and we can mount any path starting with /Users into our container. Pretty neat.

boot2docker doesn't support the VirtualBox Guest Additions that allow us to make this work. Fortunately, a very smart person has solved this problem for us with a custom build of boot2docker containing the Guest Additions and the configuration to make this all work. We just have to install it.

First, let's remove the web container and shut down our VM:

Next, we'll download the custom build:

Finally, we share the /Users directory with our VM and start it up again:

Replacing the boot2docker image won't erase any of the data in your VM, so don't worry about losing any of your containers. Good guy boot2docker.

Let's try this again:

Great success! Let's verify that we're using a volume by creating a new file on OS X and seeing if nginx serves it up:

Sweet damn. Make sure to stop and remove the container:

Mac

If you update index.html and curl it, you won't see your changes. This is because nginx ships with sendfile turned on, which doesn't play well with VirtualBox. The solution is simple—turn off sendfile in the nginx config file—but outside the scope of this post.

Problem #3: Getting Inside a Container

The Problem: How do I get in there?

So you've got your shiny new container running. The ports are forwarding and the volumes are .. voluming. Everything's cool, until you realize something's totally uncool. You'd really like to start a shell in there and poke around.

The Solution: Linux Magic

Enter nsenter. nsenter is a program that allows you to run commands inside a kernel namespace. Since a container is just a process running inside its own kernel namespace, this is exactly what we need to start a shell inside our container. Let's make it so.

This part deals with shells running in three different places. Trés confusing. I'll use a different prompt to distinguish each:

  • >for OS X
  • $for the boot2docker VM
  • %for inside a Docker container

First, let's SSH into the boot2docker VM:

Next, install nsenter:

(How does that install it? jpetazzo/nsenter is a Docker image configured to build nsenter from source. When we start a container from this image, it builds nsenter and installs it to /target, which we've set to be a volume pointing to /var/lib/boot2docker in our VM.

Socket Up Mac Os Catalina

In other words, we start a prepackaged build environment for nsenter, which compiles and installs it to our VM using a volume. How awesome is that? Seriously, how awesome? Answer me!)

Finally, we need to add /var/lib/boot2docker to the docker user's PATH inside the VM:

We should now be able to use the installed binary:

Let's start our nginx container again and see how it works (remember, we're still SSH'd into our VM):

Time to get inside that thing. nsenter needs the pid of the running container. Let's get it:

The moment of truth:

Great success! Let's confirm we're inside our container by listing the running processes (we have to install ps first):

We can see two nginx processes, our shell, and ps. How cool is that?

Getting the pid and feeding it to nsenter is kind of a pain. jpetazzo/nsenter includes docker-enter, a shell script that does it for you:

The default command is sh, but we can run any command we want by passing it as arguments:

This is totally awesome. It would be more totally awesomer if we could do it directly from OS X. jpetazzo's got us covered there, too (that guy thinks of everything), with a bash script we can install on OS X. Below is the same script, but with a minor change to default to bash, because that's how I roll.

Just stick this bro anywhere in your OS X PATH (and chmod +x it, natch) and you're all set:

Let's test it out:

Yes. YES. Cue guitar solo.

Don't forget to stop and remove your container (nag nag nag):

The End

You now have a Docker environment running on OS X that does all the things you'd expect. You've also hopefully learned a little about how Docker works and how to use it. We've had some laughs, and we've learned a lot, too. I'm glad we're friends.

If you're ready to learn more about Docker, check out The Docker Book. I can't recommend it enough. Throw some money at that guy.

The Future Soon

Docker might be the new kid on the block, but we're already thinking about ways to add it to our workflow. Stay tuned for great justice.

Mac Os Mojave

Was this post helpful? How are you using Docker? Let me know down there in the comments box. Have a great. Call your mom.

This article explains how to work with sockets and socket streams at various levels, from POSIX through Foundation.

Important: This article describes ways to make socket connections that are completely under the control of your program. Most programs would be better served by higher-level APIs such as NSURLConnection. To learn more about these higher-level APIs, read Networking Overview.

The APIs described in this article should be used only if you need to support some protocol other than the protocols supported by built-in Cocoa or Core Foundation functionality.

At almost every level of networking, software can be divided into two categories: clients (programs that connect to other apps) and services (programs that other apps connect to). At a high level, these lines are clear. Most programs written using high-level APIs are purely clients. At a lower level, however, the lines are often blurry.

Socket and stream programming generally falls into one of the following broad categories:

  • Packet-based communication—Programs that operate on one packet at a time, listening for incoming packets, then sending packets in reply.

    With packet-based communication, the only differences between clients and servers are the contents of the packets that each program sends and receives, and (presumably) what each program does with the data. The networking code itself is identical.

  • Stream-based clients—Programs that use TCP to send and receive data as two continuous streams of bytes, one in each direction.

    With stream-based communication, clients and servers are somewhat more distinct. The actual data handling part of clients and servers is similar, but the way that the program initially constructs the communication channel is very different.

This chapter is divided into sections based on the above tasks:

  • Choosing an API Family—Describes how to decide which API family to use when writing networking code.

  • Writing a TCP-Based Client—Describes how to make outgoing TCP connections to existing servers and services.

  • Writing a TCP-Based Server—Describes how to listen for incoming TCP connections when writing servers and services.

  • Working with Packet-Based Sockets—Describes how to work with non-TCP protocols, such as UDP.

Choosing an API Family

Socket Up Mac Os X

The API you choose for socket-based connections depends on whether you are making a connection to another host or receiving a connection from another host. It also depends on whether you are using TCP or some other protocol. Here are a few factors to consider:

  • In OS X, if you already have networking code that is shared with non-Apple platforms, you can use POSIX C networking APIs and continue to use your networking code as-is (on a separate thread). If your program is based on a Core Foundation or Cocoa (Foundation) run loop, you can also use the Core Foundation CFStream API to integrate the POSIX networking code into your overall architecture on the main thread. Alternatively, if you are using Grand Central Dispatch (GCD), you can add a socket as a dispatch source.

    In iOS, POSIX networking is discouraged because it does not activate the cellular radio or on-demand VPN. Thus, as a general rule, you should separate the networking code from any common data processing functionality and rewrite the networking code using higher-level APIs.

    Note: If you use POSIX networking code, you should be aware that the POSIX networking API is not protocol-agnostic (you must handle some of the differences between IPv4 and IPv6 yourself). It is a connect-by-IP API rather than a connect-by-name API, which means that you must do a lot of extra work if you want to achieve the same initial-connection performance and robustness that higher-level APIs give you for free. Before you decide to reuse existing POSIX networking code, be sure to read Avoid Resolving DNS Names Before Connecting to a Host in Networking Overview.

  • For daemons and services that listen on a port, or for non-TCP connections, use POSIX or Core Foundation (CFSocket) C networking APIs.

  • For client code in Objective-C, use Foundation Objective-C networking APIs. Foundation defines high-level classes for managing URL connections, socket streams, network services, and other networking tasks. It is also the primary non-UI Objective-C framework in OS X and iOS, providing routines for run loops, string handling, collection objects, file access, and so on.

  • For client code in C, use Core Foundation C networking APIs. The Core Foundation framework and the CFNetwork framework are two of the primary C-language frameworks in OS X and iOS. Together they define the functions and structures upon which the Foundation networking classes are built.

    Note: In OS X, CFNetwork is a subframework of the Core Services framework; in iOS, CFNetwork is a top-level framework.

Writing a TCP-Based Client

The way you make an outgoing connection depends on what programming language you are using, on the type of connection (TCP, UDP, and so forth), and on whether you are trying to share code with other (non-Mac, non-iOS) platforms.

  • Use NSStream for outgoing connections in Objective-C.

    If you are connecting to a specific host, create a CFHost object (not NSHost—they are not toll-free bridged), then use CFStreamCreatePairWithSocketToHost or CFStreamCreatePairWithSocketToCFHost to open a socket connected to that host and port and associate a pair of CFStream objects with it. You can then cast these to an NSStream object.

    You can also use the CFStreamCreatePairWithSocketToNetService function with a CFNetServiceRef object to connect to a Bonjour service. Read Discovering and Advertising Network Services in Networking Overview for more information.

    Note: The getStreamsToHost:port:inputStream:outputStream: method of NSNetService is not available on iOS, and is discouraged on OS X for performance reasons. Specifically, NSNetService requires you to create an instance of NSHost. When you create the object, the lookup is performed synchronously. Thus, it is unsafe to construct an NSHost object on your main application thread. See NSNetService and Automatic Reference Counting (ARC) for details.

  • Use CFStream for outgoing connections in C.

    If you are writing code that cannot include Objective-C, use the CFStream API. It integrates more easily with other Core Foundation APIs than CFSocket, and enables the cellular hardware on iOS (where applicable), unlike lower-level APIs. You can use CFStreamCreatePairWithSocketToHost or CFStreamCreatePairWithSocketToCFHost to open a socket connected to a given host and port and associate a pair of CFStream objects with it.

    You can also use the CFStreamCreatePairWithSocketToNetService function to connect to a Bonjour service. Read Discovering and Advertising Network Services in Networking Overview for more information.

  • Use POSIX calls if cross-platform portability is required.

    If you are writing networking code that runs exclusively in OS X and iOS, you should generally avoid POSIX networking calls, because they are harder to work with than higher-level APIs. However, if you are writing networking code that must be shared with other platforms, you can use the POSIX networking APIs so that you can use the same code everywhere.

    Never use synchronous POSIX networking APIs on the main thread of a GUI application. If you use synchronous networking calls in a GUI application, you must do so on a separate thread.

    Note: POSIX networking does not activate the cellular radio on iOS. For this reason, the POSIX networking API is generally discouraged in iOS.

The subsections below describe the use of NSStream. Except where noted, the CFStream API has functions with similar names, and behaves similarly.

To learn more about the POSIX socket API, read the UNIX Socket FAQ at http://developerweb.net/.

Establishing a Connection

As a rule, the recommended way to establish a TCP connection to a remote host is with streams. Streams automatically handle many of the challenges that TCP connections present. For example, streams provide the ability to connect by hostname, and in iOS, they automatically activate a device's cellular modem or on-demand VPN when needed (unlike CFSocket or BSD sockets). Streams are also a more Cocoa-like networking interface than lower-level protocols, behaving in a way that is largely compatible with the Cocoa file stream APIs.

The way you obtain input and output streams for a host depends on whether you used service discovery to discover the host:

  • If you already know the DNS name or IP address of the remote host, obtain Core Foundation read (input) and write (output) streams with the CFStreamCreatePairWithSocketToHost function. You can then take advantage of the toll-free bridge between CFStream and NSStream to cast your CFReadStreamRef and CFWriteStreamRef objects to NSInputStream and NSOutputStream objects.

  • If you discovered the host by browsing for network services with a CFNetServiceBrowser object, you obtain input and output streams for the service with the CFStreamCreatePairWithSocketToNetService function. Read Discovering and Advertising Network Services in Networking Overview for more information.

After you have obtained your input and output streams, you should retain them immediately if you are not using automatic reference counting. Then cast them to NSInputStream and NSOutputStream objects, set their delegate objects (which should conform to the NSStreamDelegate protocol), schedule them on the current run loop, and call their open methods.

Note: If you are working with more than one connection at a time, you must also keep track of which input stream is associated with a given output stream and vice versa. The most straightforward way to do this is to create your own connection object that holds references to both streams, and then set that object as the delegate for each stream.

Handling Events

When the stream:handleEvent: method is called on the NSOutputStream object's delegate and the streamEvent parameter's value is NSStreamEventHasSpaceAvailable, call write:maxLength: to send data. This method returns the number of bytes written or a negative number on error. If fewer bytes were written than you tried to send, you must queue up the remaining data and send it after the delegate method gets called again with an NSStreamEventHasSpaceAvailable event. If an error occurs, you should call streamError to find out what went wrong.

When the stream:handleEvent: method is called on your NSInputStream object's delegate and the streamEvent parameter's value is NSStreamEventHasBytesAvailable, your input stream has received data that you can read with the read:maxLength: method. This method returns the number of bytes read, or a negative number on error.

If fewer bytes were read than you need, you must queue the data and wait until you receive another stream event with additional data. If an error occurs, you should call streamError to find out what went wrong.

If the other end of the connection closes the connection:

  • Your connection delegate's stream:handleEvent: method is called with streamEvent set to NSStreamEventHasBytesAvailable. When you read from that stream, you get a length of zero (0).

  • Your connection delegate's stream:handleEvent: method is called with streamEvent set to NSStreamEventEndEncountered.

When either of these two events occurs, the delegate method is responsible for detecting the end-of-file condition and cleaning up.

Closing the Connection

To close your connection, unschedule it from the run loop, set the connection's delegate to nil (the delegate is unretained), close both of the associated streams with the close method, and then release the streams themselves (if you are not using ARC) or set them to nil (if you are). By default, this closes the underlying socket connection. There are two situations in which you must close it yourself, however:

  • If you previously set the kCFStreamPropertyShouldCloseNativeSocket to kCFBooleanFalse by calling setProperty:forKey: on the stream.

  • If you created the streams based on an existing BSD socket by calling CFStreamCreatePairWithSocket.

    By default, streams created from an existing native socket do not close their underlying socket. However, you can enable automatic closing by setting the kCFStreamPropertyShouldCloseNativeSocket to kCFBooleanTrue with the setProperty:forKey: method.

For More Information

To learn more, read Setting Up Socket Streams in Stream Programming Guide, Using NSStreams For A TCP Connection Without NSHost, or see the SimpleNetworkStreams and RemoteCurrency sample code projects.

Writing a TCP-Based Server

As mentioned previously, a server and a client are similar once the connection is established. The main difference is that clients make outgoing connections, whereas servers create a listening socket (sometimes listen socket)—a socket that listens for incoming connections—then accept connections on that socket. After that, each resulting connection behaves just like a connection you might make in a client.

The API you should choose for your server depends primarily on whether you are trying to share the code with other (non-Mac, non-iOS) platforms. There are only two APIs that provide the ability to listen for incoming network connections: the Core Foundation socket API and the POSIX (BSD) socket API. Higher-level APIs cannot be used for accepting incoming connections.

  • If you are writing code for OS X and iOS exclusively, use POSIX networking calls to set up your network sockets. Then, use GCD or CFSocket to integrate the sockets into your run loop.

  • Use pure POSIX networking code with a POSIX-based run loop (select) if cross-platform portability with non-Apple platforms is required.

    If you are writing networking code that runs exclusively in OS X and iOS, you should generally avoid POSIX networking calls because they are harder to work with than higher level APIs. However, if you are writing networking code that must be shared with other platforms, you can use the POSIX networking APIs so that you can use the same code everywhere.

  • Never use NSSocketPort or NSFileHandle for general socket communication. For details, see Do Not Use NSSocketPort (OS X) or NSFileHandle for General Socket Communication in Networking Overview.

4th of january mac os. The following sections describe how to use these APIs to listen for incoming connections.

Listening with Core Foundation

To use Core Foundation APIs to listen for incoming connections, you must do the following:

  1. Add appropriate includes:

  2. Create socket objects (returned as a CFSocketRef object) with the CFSocketCreate or CFSocketCreateWithNative function. Specify kCFSocketAcceptCallBack as the callBackTypes parameter value. Provide a pointer to a CFSocketCallBack callback function as the callout parameter value.

  3. Bind a socket with the CFSocketSetAddress function. Provide a CFData object containing a sockaddr struct that specifies information about the desired port and family.

  4. Begin listening on a socket by adding the socket to a run loop.

    Create a run-loop source for a socket with the CFSocketCreateRunLoopSource function. Then, add the socket to a run loop by providing its run-loop source to the CFRunLoopAddSource function.

After this, you can access the underlying BSD socket descriptor with the CFSocketGetNative function.

When you are through with the socket, you must close it by calling CFSocketInvalidate.

In your listening socket's callback function (handleConnect in this case), you should check to make sure the value of the callbackType parameter is kCFSocketAcceptCallBack, which means that a new connection has been accepted. In this case, the data parameter of the callback is a pointer to a CFSocketNativeHandle value (an integer socket number) representing the socket.

To handle the new incoming connections, you can use the CFStream, NSStream, or CFSocket APIs. The stream-based APIs are strongly recommended.

To do this:

  1. Create read and write streams for the socket with the CFStreamCreatePairWithSocket function.

  2. Cast the streams to an NSInputStream object and an NSOutputStream object if you are working in Cocoa.

  3. Use the streams as described in Writing a TCP-Based Client.

For more information, see CFSocket Reference. For sample code, see the RemoteCurrency and WiTap sample code projects.

Listening with POSIX Socket APIs

POSIX networking is fairly similar to the CFSocket API, except that you have to write your own run-loop-handling code.

Important: Never use POSIX networking APIs on the main thread of a GUI application. If you use POSIX networking in a GUI application, you must either do so on a separate thread or use GCD.

Here are the basic steps for creating a POSIX-level server:

  1. Create a socket by calling socket. For example:

  2. Bind it to a port.

    • If you have a specific port in mind, use that.

    • If you don't have a specific port in mind, pass zero for the port number, and the operating system will assign you an ephemeral port. (If you are going to advertise your service with Bonjour, you should almost always use an ephemeral port.)

    For example:

  3. If you are using an ephemeral port, call getsockname to find out what port you are using. You can then register this port with Bonjour. For example:

  4. Call listen to begin listening for incoming connections on that port.

The next steps depend on whether you intend to use pure POSIX socket code or a higher level abstraction.

Handling Events with Core Foundation

Call CFSocketCreateWithNative. Then follow the directions in Listening with Core Foundation, beginning at step 3.

Handling Events with Grand Central Dispatch

GCD allows you to perform operations asynchronously, and provides an event queue mechanism for determining when to read data from the socket. After creating the listening socket, a GCD-based server should:

  1. Call dispatch_source_create to create a dispatch source for the listening socket, specifying DISPATCH_SOURCE_TYPE_READ as the source type.

  2. Call dispatch_source_set_event_handler (or dispatch_source_set_event_handler_f and dispatch_set_context) to set a handler that gets called whenever a new connection arrives on the socket.

  3. When the listen socket handler is called (upon a new connection), it should:

    • Call accept. This function fills a new sockaddr structure with information about the connection and returns a new socket for that connection.

      If desired, call ntohl(my_sockaddr_obj.sin_addr.s_addr) to determine the client's IP address.

    • Call dispatch_source_create to create a dispatch source for the client socket, specifying DISPATCH_SOURCE_TYPE_READ as the source type.

    • Call setsockopt to set the SO_NOSIGPIPE flag on the socket.

    • Call dispatch_source_set_event_handler (or dispatch_source_set_event_handler_f and dispatch_set_context) to set a handler that gets called whenever the state of the connection changes.

  4. In the client socket handler, call dispatch_async or dispatch_async_f and pass a block that calls read on the socket to grab any new data, then handle that data appropriately. This block can also send responses by calling write on the socket.

Handling Events with Pure POSIX Code

  1. Create a file descriptor set and add new sockets to that set as new connections come in.

  2. If you need to perform actions periodically on your networking thread, construct a timeval structure for the select timeout.

    It is important to choose a timeout that is reasonable. Short timeout values bog down the system by causing your process to run more frequently than is necessary. Unless you are doing something very unusual, your select loop should not wake more than a few times per second, at most, and on iOS, you should try to avoid doing this at all. For alternatives, read Avoid POSIX Sockets and CFSocket on iOS Where Possible in Networking Overview.

    If you do not need to perform periodic actions, pass NULL.

  3. Call select in a loop, passing two separate copies of that file descriptor set (created by calling FD_COPY) for the read and write descriptor sets. The select system call modifies these descriptor sets, clearing any descriptors that are not ready for reading or writing.

    For the timeout parameter, pass the timeval structure you created earlier. Although OS X and iOS do not modify this structure, some other operating systems replace this value with the amount of time remaining. Thus, for cross-platform compatibility, you must reset this value each time you call select.

    For the nfds parameter, pass a number that is one higher than the highest-numbered file descriptor that is actually in use.

  4. Read data from sockets, calling FD_ISSET to determine if a given socket has pending data.

    Write data to calling FD_ISSET to determine if a given socket has room for new data.

    Maintain appropriate queues for incoming and outgoing data.

Socket Up Mac OS

If you update index.html and curl it, you won't see your changes. This is because nginx ships with sendfile turned on, which doesn't play well with VirtualBox. The solution is simple—turn off sendfile in the nginx config file—but outside the scope of this post.

Problem #3: Getting Inside a Container

The Problem: How do I get in there?

So you've got your shiny new container running. The ports are forwarding and the volumes are .. voluming. Everything's cool, until you realize something's totally uncool. You'd really like to start a shell in there and poke around.

The Solution: Linux Magic

Enter nsenter. nsenter is a program that allows you to run commands inside a kernel namespace. Since a container is just a process running inside its own kernel namespace, this is exactly what we need to start a shell inside our container. Let's make it so.

This part deals with shells running in three different places. Trés confusing. I'll use a different prompt to distinguish each:

  • >for OS X
  • $for the boot2docker VM
  • %for inside a Docker container

First, let's SSH into the boot2docker VM:

Next, install nsenter:

(How does that install it? jpetazzo/nsenter is a Docker image configured to build nsenter from source. When we start a container from this image, it builds nsenter and installs it to /target, which we've set to be a volume pointing to /var/lib/boot2docker in our VM.

Socket Up Mac Os Catalina

In other words, we start a prepackaged build environment for nsenter, which compiles and installs it to our VM using a volume. How awesome is that? Seriously, how awesome? Answer me!)

Finally, we need to add /var/lib/boot2docker to the docker user's PATH inside the VM:

We should now be able to use the installed binary:

Let's start our nginx container again and see how it works (remember, we're still SSH'd into our VM):

Time to get inside that thing. nsenter needs the pid of the running container. Let's get it:

The moment of truth:

Great success! Let's confirm we're inside our container by listing the running processes (we have to install ps first):

We can see two nginx processes, our shell, and ps. How cool is that?

Getting the pid and feeding it to nsenter is kind of a pain. jpetazzo/nsenter includes docker-enter, a shell script that does it for you:

The default command is sh, but we can run any command we want by passing it as arguments:

This is totally awesome. It would be more totally awesomer if we could do it directly from OS X. jpetazzo's got us covered there, too (that guy thinks of everything), with a bash script we can install on OS X. Below is the same script, but with a minor change to default to bash, because that's how I roll.

Just stick this bro anywhere in your OS X PATH (and chmod +x it, natch) and you're all set:

Let's test it out:

Yes. YES. Cue guitar solo.

Don't forget to stop and remove your container (nag nag nag):

The End

You now have a Docker environment running on OS X that does all the things you'd expect. You've also hopefully learned a little about how Docker works and how to use it. We've had some laughs, and we've learned a lot, too. I'm glad we're friends.

If you're ready to learn more about Docker, check out The Docker Book. I can't recommend it enough. Throw some money at that guy.

The Future Soon

Docker might be the new kid on the block, but we're already thinking about ways to add it to our workflow. Stay tuned for great justice.

Mac Os Mojave

Was this post helpful? How are you using Docker? Let me know down there in the comments box. Have a great. Call your mom.

This article explains how to work with sockets and socket streams at various levels, from POSIX through Foundation.

Important: This article describes ways to make socket connections that are completely under the control of your program. Most programs would be better served by higher-level APIs such as NSURLConnection. To learn more about these higher-level APIs, read Networking Overview.

The APIs described in this article should be used only if you need to support some protocol other than the protocols supported by built-in Cocoa or Core Foundation functionality.

At almost every level of networking, software can be divided into two categories: clients (programs that connect to other apps) and services (programs that other apps connect to). At a high level, these lines are clear. Most programs written using high-level APIs are purely clients. At a lower level, however, the lines are often blurry.

Socket and stream programming generally falls into one of the following broad categories:

  • Packet-based communication—Programs that operate on one packet at a time, listening for incoming packets, then sending packets in reply.

    With packet-based communication, the only differences between clients and servers are the contents of the packets that each program sends and receives, and (presumably) what each program does with the data. The networking code itself is identical.

  • Stream-based clients—Programs that use TCP to send and receive data as two continuous streams of bytes, one in each direction.

    With stream-based communication, clients and servers are somewhat more distinct. The actual data handling part of clients and servers is similar, but the way that the program initially constructs the communication channel is very different.

This chapter is divided into sections based on the above tasks:

  • Choosing an API Family—Describes how to decide which API family to use when writing networking code.

  • Writing a TCP-Based Client—Describes how to make outgoing TCP connections to existing servers and services.

  • Writing a TCP-Based Server—Describes how to listen for incoming TCP connections when writing servers and services.

  • Working with Packet-Based Sockets—Describes how to work with non-TCP protocols, such as UDP.

Choosing an API Family

Socket Up Mac Os X

The API you choose for socket-based connections depends on whether you are making a connection to another host or receiving a connection from another host. It also depends on whether you are using TCP or some other protocol. Here are a few factors to consider:

  • In OS X, if you already have networking code that is shared with non-Apple platforms, you can use POSIX C networking APIs and continue to use your networking code as-is (on a separate thread). If your program is based on a Core Foundation or Cocoa (Foundation) run loop, you can also use the Core Foundation CFStream API to integrate the POSIX networking code into your overall architecture on the main thread. Alternatively, if you are using Grand Central Dispatch (GCD), you can add a socket as a dispatch source.

    In iOS, POSIX networking is discouraged because it does not activate the cellular radio or on-demand VPN. Thus, as a general rule, you should separate the networking code from any common data processing functionality and rewrite the networking code using higher-level APIs.

    Note: If you use POSIX networking code, you should be aware that the POSIX networking API is not protocol-agnostic (you must handle some of the differences between IPv4 and IPv6 yourself). It is a connect-by-IP API rather than a connect-by-name API, which means that you must do a lot of extra work if you want to achieve the same initial-connection performance and robustness that higher-level APIs give you for free. Before you decide to reuse existing POSIX networking code, be sure to read Avoid Resolving DNS Names Before Connecting to a Host in Networking Overview.

  • For daemons and services that listen on a port, or for non-TCP connections, use POSIX or Core Foundation (CFSocket) C networking APIs.

  • For client code in Objective-C, use Foundation Objective-C networking APIs. Foundation defines high-level classes for managing URL connections, socket streams, network services, and other networking tasks. It is also the primary non-UI Objective-C framework in OS X and iOS, providing routines for run loops, string handling, collection objects, file access, and so on.

  • For client code in C, use Core Foundation C networking APIs. The Core Foundation framework and the CFNetwork framework are two of the primary C-language frameworks in OS X and iOS. Together they define the functions and structures upon which the Foundation networking classes are built.

    Note: In OS X, CFNetwork is a subframework of the Core Services framework; in iOS, CFNetwork is a top-level framework.

Writing a TCP-Based Client

The way you make an outgoing connection depends on what programming language you are using, on the type of connection (TCP, UDP, and so forth), and on whether you are trying to share code with other (non-Mac, non-iOS) platforms.

  • Use NSStream for outgoing connections in Objective-C.

    If you are connecting to a specific host, create a CFHost object (not NSHost—they are not toll-free bridged), then use CFStreamCreatePairWithSocketToHost or CFStreamCreatePairWithSocketToCFHost to open a socket connected to that host and port and associate a pair of CFStream objects with it. You can then cast these to an NSStream object.

    You can also use the CFStreamCreatePairWithSocketToNetService function with a CFNetServiceRef object to connect to a Bonjour service. Read Discovering and Advertising Network Services in Networking Overview for more information.

    Note: The getStreamsToHost:port:inputStream:outputStream: method of NSNetService is not available on iOS, and is discouraged on OS X for performance reasons. Specifically, NSNetService requires you to create an instance of NSHost. When you create the object, the lookup is performed synchronously. Thus, it is unsafe to construct an NSHost object on your main application thread. See NSNetService and Automatic Reference Counting (ARC) for details.

  • Use CFStream for outgoing connections in C.

    If you are writing code that cannot include Objective-C, use the CFStream API. It integrates more easily with other Core Foundation APIs than CFSocket, and enables the cellular hardware on iOS (where applicable), unlike lower-level APIs. You can use CFStreamCreatePairWithSocketToHost or CFStreamCreatePairWithSocketToCFHost to open a socket connected to a given host and port and associate a pair of CFStream objects with it.

    You can also use the CFStreamCreatePairWithSocketToNetService function to connect to a Bonjour service. Read Discovering and Advertising Network Services in Networking Overview for more information.

  • Use POSIX calls if cross-platform portability is required.

    If you are writing networking code that runs exclusively in OS X and iOS, you should generally avoid POSIX networking calls, because they are harder to work with than higher-level APIs. However, if you are writing networking code that must be shared with other platforms, you can use the POSIX networking APIs so that you can use the same code everywhere.

    Never use synchronous POSIX networking APIs on the main thread of a GUI application. If you use synchronous networking calls in a GUI application, you must do so on a separate thread.

    Note: POSIX networking does not activate the cellular radio on iOS. For this reason, the POSIX networking API is generally discouraged in iOS.

The subsections below describe the use of NSStream. Except where noted, the CFStream API has functions with similar names, and behaves similarly.

To learn more about the POSIX socket API, read the UNIX Socket FAQ at http://developerweb.net/.

Establishing a Connection

As a rule, the recommended way to establish a TCP connection to a remote host is with streams. Streams automatically handle many of the challenges that TCP connections present. For example, streams provide the ability to connect by hostname, and in iOS, they automatically activate a device's cellular modem or on-demand VPN when needed (unlike CFSocket or BSD sockets). Streams are also a more Cocoa-like networking interface than lower-level protocols, behaving in a way that is largely compatible with the Cocoa file stream APIs.

The way you obtain input and output streams for a host depends on whether you used service discovery to discover the host:

  • If you already know the DNS name or IP address of the remote host, obtain Core Foundation read (input) and write (output) streams with the CFStreamCreatePairWithSocketToHost function. You can then take advantage of the toll-free bridge between CFStream and NSStream to cast your CFReadStreamRef and CFWriteStreamRef objects to NSInputStream and NSOutputStream objects.

  • If you discovered the host by browsing for network services with a CFNetServiceBrowser object, you obtain input and output streams for the service with the CFStreamCreatePairWithSocketToNetService function. Read Discovering and Advertising Network Services in Networking Overview for more information.

After you have obtained your input and output streams, you should retain them immediately if you are not using automatic reference counting. Then cast them to NSInputStream and NSOutputStream objects, set their delegate objects (which should conform to the NSStreamDelegate protocol), schedule them on the current run loop, and call their open methods.

Note: If you are working with more than one connection at a time, you must also keep track of which input stream is associated with a given output stream and vice versa. The most straightforward way to do this is to create your own connection object that holds references to both streams, and then set that object as the delegate for each stream.

Handling Events

When the stream:handleEvent: method is called on the NSOutputStream object's delegate and the streamEvent parameter's value is NSStreamEventHasSpaceAvailable, call write:maxLength: to send data. This method returns the number of bytes written or a negative number on error. If fewer bytes were written than you tried to send, you must queue up the remaining data and send it after the delegate method gets called again with an NSStreamEventHasSpaceAvailable event. If an error occurs, you should call streamError to find out what went wrong.

When the stream:handleEvent: method is called on your NSInputStream object's delegate and the streamEvent parameter's value is NSStreamEventHasBytesAvailable, your input stream has received data that you can read with the read:maxLength: method. This method returns the number of bytes read, or a negative number on error.

If fewer bytes were read than you need, you must queue the data and wait until you receive another stream event with additional data. If an error occurs, you should call streamError to find out what went wrong.

If the other end of the connection closes the connection:

  • Your connection delegate's stream:handleEvent: method is called with streamEvent set to NSStreamEventHasBytesAvailable. When you read from that stream, you get a length of zero (0).

  • Your connection delegate's stream:handleEvent: method is called with streamEvent set to NSStreamEventEndEncountered.

When either of these two events occurs, the delegate method is responsible for detecting the end-of-file condition and cleaning up.

Closing the Connection

To close your connection, unschedule it from the run loop, set the connection's delegate to nil (the delegate is unretained), close both of the associated streams with the close method, and then release the streams themselves (if you are not using ARC) or set them to nil (if you are). By default, this closes the underlying socket connection. There are two situations in which you must close it yourself, however:

  • If you previously set the kCFStreamPropertyShouldCloseNativeSocket to kCFBooleanFalse by calling setProperty:forKey: on the stream.

  • If you created the streams based on an existing BSD socket by calling CFStreamCreatePairWithSocket.

    By default, streams created from an existing native socket do not close their underlying socket. However, you can enable automatic closing by setting the kCFStreamPropertyShouldCloseNativeSocket to kCFBooleanTrue with the setProperty:forKey: method.

For More Information

To learn more, read Setting Up Socket Streams in Stream Programming Guide, Using NSStreams For A TCP Connection Without NSHost, or see the SimpleNetworkStreams and RemoteCurrency sample code projects.

Writing a TCP-Based Server

As mentioned previously, a server and a client are similar once the connection is established. The main difference is that clients make outgoing connections, whereas servers create a listening socket (sometimes listen socket)—a socket that listens for incoming connections—then accept connections on that socket. After that, each resulting connection behaves just like a connection you might make in a client.

The API you should choose for your server depends primarily on whether you are trying to share the code with other (non-Mac, non-iOS) platforms. There are only two APIs that provide the ability to listen for incoming network connections: the Core Foundation socket API and the POSIX (BSD) socket API. Higher-level APIs cannot be used for accepting incoming connections.

  • If you are writing code for OS X and iOS exclusively, use POSIX networking calls to set up your network sockets. Then, use GCD or CFSocket to integrate the sockets into your run loop.

  • Use pure POSIX networking code with a POSIX-based run loop (select) if cross-platform portability with non-Apple platforms is required.

    If you are writing networking code that runs exclusively in OS X and iOS, you should generally avoid POSIX networking calls because they are harder to work with than higher level APIs. However, if you are writing networking code that must be shared with other platforms, you can use the POSIX networking APIs so that you can use the same code everywhere.

  • Never use NSSocketPort or NSFileHandle for general socket communication. For details, see Do Not Use NSSocketPort (OS X) or NSFileHandle for General Socket Communication in Networking Overview.

4th of january mac os. The following sections describe how to use these APIs to listen for incoming connections.

Listening with Core Foundation

To use Core Foundation APIs to listen for incoming connections, you must do the following:

  1. Add appropriate includes:

  2. Create socket objects (returned as a CFSocketRef object) with the CFSocketCreate or CFSocketCreateWithNative function. Specify kCFSocketAcceptCallBack as the callBackTypes parameter value. Provide a pointer to a CFSocketCallBack callback function as the callout parameter value.

  3. Bind a socket with the CFSocketSetAddress function. Provide a CFData object containing a sockaddr struct that specifies information about the desired port and family.

  4. Begin listening on a socket by adding the socket to a run loop.

    Create a run-loop source for a socket with the CFSocketCreateRunLoopSource function. Then, add the socket to a run loop by providing its run-loop source to the CFRunLoopAddSource function.

After this, you can access the underlying BSD socket descriptor with the CFSocketGetNative function.

When you are through with the socket, you must close it by calling CFSocketInvalidate.

In your listening socket's callback function (handleConnect in this case), you should check to make sure the value of the callbackType parameter is kCFSocketAcceptCallBack, which means that a new connection has been accepted. In this case, the data parameter of the callback is a pointer to a CFSocketNativeHandle value (an integer socket number) representing the socket.

To handle the new incoming connections, you can use the CFStream, NSStream, or CFSocket APIs. The stream-based APIs are strongly recommended.

To do this:

  1. Create read and write streams for the socket with the CFStreamCreatePairWithSocket function.

  2. Cast the streams to an NSInputStream object and an NSOutputStream object if you are working in Cocoa.

  3. Use the streams as described in Writing a TCP-Based Client.

For more information, see CFSocket Reference. For sample code, see the RemoteCurrency and WiTap sample code projects.

Listening with POSIX Socket APIs

POSIX networking is fairly similar to the CFSocket API, except that you have to write your own run-loop-handling code.

Important: Never use POSIX networking APIs on the main thread of a GUI application. If you use POSIX networking in a GUI application, you must either do so on a separate thread or use GCD.

Here are the basic steps for creating a POSIX-level server:

  1. Create a socket by calling socket. For example:

  2. Bind it to a port.

    • If you have a specific port in mind, use that.

    • If you don't have a specific port in mind, pass zero for the port number, and the operating system will assign you an ephemeral port. (If you are going to advertise your service with Bonjour, you should almost always use an ephemeral port.)

    For example:

  3. If you are using an ephemeral port, call getsockname to find out what port you are using. You can then register this port with Bonjour. For example:

  4. Call listen to begin listening for incoming connections on that port.

The next steps depend on whether you intend to use pure POSIX socket code or a higher level abstraction.

Handling Events with Core Foundation

Call CFSocketCreateWithNative. Then follow the directions in Listening with Core Foundation, beginning at step 3.

Handling Events with Grand Central Dispatch

GCD allows you to perform operations asynchronously, and provides an event queue mechanism for determining when to read data from the socket. After creating the listening socket, a GCD-based server should:

  1. Call dispatch_source_create to create a dispatch source for the listening socket, specifying DISPATCH_SOURCE_TYPE_READ as the source type.

  2. Call dispatch_source_set_event_handler (or dispatch_source_set_event_handler_f and dispatch_set_context) to set a handler that gets called whenever a new connection arrives on the socket.

  3. When the listen socket handler is called (upon a new connection), it should:

    • Call accept. This function fills a new sockaddr structure with information about the connection and returns a new socket for that connection.

      If desired, call ntohl(my_sockaddr_obj.sin_addr.s_addr) to determine the client's IP address.

    • Call dispatch_source_create to create a dispatch source for the client socket, specifying DISPATCH_SOURCE_TYPE_READ as the source type.

    • Call setsockopt to set the SO_NOSIGPIPE flag on the socket.

    • Call dispatch_source_set_event_handler (or dispatch_source_set_event_handler_f and dispatch_set_context) to set a handler that gets called whenever the state of the connection changes.

  4. In the client socket handler, call dispatch_async or dispatch_async_f and pass a block that calls read on the socket to grab any new data, then handle that data appropriately. This block can also send responses by calling write on the socket.

Handling Events with Pure POSIX Code

  1. Create a file descriptor set and add new sockets to that set as new connections come in.

  2. If you need to perform actions periodically on your networking thread, construct a timeval structure for the select timeout.

    It is important to choose a timeout that is reasonable. Short timeout values bog down the system by causing your process to run more frequently than is necessary. Unless you are doing something very unusual, your select loop should not wake more than a few times per second, at most, and on iOS, you should try to avoid doing this at all. For alternatives, read Avoid POSIX Sockets and CFSocket on iOS Where Possible in Networking Overview.

    If you do not need to perform periodic actions, pass NULL.

  3. Call select in a loop, passing two separate copies of that file descriptor set (created by calling FD_COPY) for the read and write descriptor sets. The select system call modifies these descriptor sets, clearing any descriptors that are not ready for reading or writing.

    For the timeout parameter, pass the timeval structure you created earlier. Although OS X and iOS do not modify this structure, some other operating systems replace this value with the amount of time remaining. Thus, for cross-platform compatibility, you must reset this value each time you call select.

    For the nfds parameter, pass a number that is one higher than the highest-numbered file descriptor that is actually in use.

  4. Read data from sockets, calling FD_ISSET to determine if a given socket has pending data.

    Write data to calling FD_ISSET to determine if a given socket has room for new data.

    Maintain appropriate queues for incoming and outgoing data.

As an alternative to the POSIX select function, the BSD-specific kqueue API can also be used to handle socket events.

For More Information

To learn more about POSIX networking, read the socket, listen, FD_SET, and select manual pages.

Working with Packet-Based Sockets

The recommended way to send and receive UDP packets is by combining the POSIX API and either the CFSocket or GCD APIs. To use these APIs, you must perform the following steps:

  1. Create a socket by calling socket.

  2. Bind the socket by calling bind. Provide a sockaddr struct that specifies information about the desired port and family.

  3. Connect the socket by calling connect (optional).

    Note that a connected UDP socket is not a connection in the purest sense of the word. However, it provides two advantages over an unconnected socket. First, it removes the need to specify the destination address every time you send a new message. Second, your app may receive errors when a packet cannot be delivered. This error delivery is not guaranteed with UDP, however; it is dependent on network conditions that are beyond your app's control.

From there, you can work with the connection in three ways:

  • If you are using GCD for run loop integration (recommended), create a dispatch source by calling dispatch_source_create. Assign an event handler to the dispatch source. Optionally assign a cancellation handler. Finally, pass the dispatch source to the dispatch_resume function to begin handling events.

  • If you are using CFSocket for integration, this technique is somewhat more complicated, but makes it easier to interface your code with some Cocoa APIs. However, CFSocket objects use a single object to represent a connection (much like sockets at the POSIX layer), whereas most Cocoa APIs are designed to interface with stream-based APIs that use separate objects for sending and receiving. As a result, some Cocoa APIs that expect read or write streams may be difficult to use in conjunction with CFSocketRef objects.

    To use CFSocket:

    1. Create an object to use for managing the connection. If you are writing Objective-C code, this can be a class. If you are writing pure C code, this should be a Core Foundation object, such as a mutable dictionary.

    2. Create a context object to describe that object.

    3. Create a CFSocket object (CFSocketRef) for the CFSocketNativeHandle object by calling CFSocketCreateWithNative.

      Be sure to set (at minimum) the kCFSocketDataCallBack flag in your callBackTypes parameter value. Do not set the kCFSocketAcceptCallBack flag.

      You'll also need to provide a pointer to a CFSocketCallBack callback function as the callout parameter value.

      For example:

    4. Tell Core Foundation that it is allowed to close the socket when the underlying Core Foundation object is invalidated.

    5. Create an event source for the socket and schedule it on your run loop.

    Whenever new data becomes available, the data handler callback gets called. In your callback, if the value of the callbackType parameter is kCFSocketConnectCallBack, check the data parameter passed into the callback. If it is NULL, you have connected to the host. You can then send data using the CFSocketSendData function.

    When you are finished with the socket, close and invalidate it by calling the CFSocketInvalidate function.

    At any point, you can also access the underlying BSD socket by calling the CFSocketGetNative function.

    For more information, see CFSocket Reference. For sample code, see the UDPEcho sample code project.

  • If you are using pure POSIX sockets, use the select system call to wait for data, then use the read and write system calls to perform I/O. To learn more about sending and receiving UDP packets with the POSIX socket API, read the UNIX Socket FAQ at http://developerweb.net/.

Obtaining the Native Socket Handle for a Socket Stream

Sometimes when working with socket-based streams (NSInputStream, NSOutputStream, CFReadStream, or CFWriteStream), you may need to obtain the underlying socket handle associated with a stream. For example, you might want to find out the IP address and port number for each end of the stream with getsockname and getpeername, or set socket options with setsockopt.

To obtain the native socket handle for an input stream, call the following method:

You can do the same thing with an output stream, but you only need to do this with one or the other because the input and output streams for a given connection always share the same underlying native socket.

Note: If you are working with a Core Foundation stream, you can do the same thing with CFReadStreamCopyProperty, CFDataGetLength, and CFDataGetBytes.



Copyright © 2013 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2013-09-17





broken image