转自:https://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/UsingSocketsandSocketStreams.html
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:
-
Create a socket by calling
socket
. -
Bind the socket by calling
bind
. Provide asockaddr
struct that specifies information about the desired port and family. -
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 thedispatch_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 withCFSocketRef
objects.To use
CFSocket
:-
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.
-
Create a context object to describe that object.
CFSocketContext ctxt;
ctxt.version = 0;
ctxt.info = my_context_object;
ctxt.retain = CFRetain;
ctxt.release = CFRelease;
ctxt.copyDescription = NULL;
-
Create a
CFSocket
object (CFSocketRef
) for theCFSocketNativeHandle
object by callingCFSocketCreateWithNative
.Be sure to set (at minimum) the
kCFSocketDataCallBack
flag in yourcallBackTypes
parameter value. Do not set thekCFSocketAcceptCallBack
flag.You’ll also need to provide a pointer to a
CFSocketCallBack
callback function as the callout parameter value.For example:
CFSocketRef connection = CFSocketCreateWithNative(kCFAllocatorDefault,
sock,
kCFSocketDataCallBack,
handleNetworkData,
&ctxt);
-
Tell Core Foundation that it is allowed to close the socket when the underlying Core Foundation object is invalidated.
CFOptionFlags sockopt = CFSocketGetSocketFlags(connection);
sockopt |= kCFSocketCloseOnInvalidate | kCFSocketAutomaticallyReenableReadCallBack;
CFSocketSetSocketFlags(connection, sockopt);
-
Create an event source for the socket and schedule it on your run loop.
CFRunLoopSourceRef socketsource = CFSocketCreateRunLoopSource(
kCFAllocatorDefault,
connection,
0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), socketsource, kCFRunLoopDefaultMode);
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 isNULL
, you have connected to the host. You can then send data using theCFSocketSendData
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 theread
andwrite
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/.