WWDC2001 Session 136

Transcript

Kind: captions
Language: en
welcome we're gonna have a session no
136 sound the networking for games I'd
like to welcome you all I love David
Hill and table Previn will be giving
this presentation we're gonna do a
tag-team event right here I think
David's gonna lead it off talking about
some sound and specific sounding games
issues and talking about both the core
graphics and sound manager and then Todd
will follow up we're talking about
networking talking about all the various
networking services we have across the
OS for games so without further ado
David Hill for sound so as Jeff
mentioned Todd and I will be splitting
this session I'm gonna start out give
you kind of a brief overview of the
api's that we have available on Mac OS
10 and cover some of your options cover
a little bit about how to set up and
initialize each one then talk briefly
about how to play back you know sound
sample that's actually gonna be in core
audience replay back and forth at all
leverage quick time to do the one-page
mp3 player then Todd is going to come up
a little later and talk about a number
of different networking issues bsd
sockets addressing setup and
initialization and some of the network
technologies you might want to look into
using for your games at Mac OS 10 and
finally follow up and finish up with
some tips and tricks so as far as the
technologies were going to cover today
as I said I'm gonna start out with the
carbon sound manager tell you a little
bit about what's changed and what hasn't
I'm going to talk briefly about
QuickTime in core audio and then Todd is
going to be covering open transport Nets
broken open play and some bsd sockets
to the carbon soundmanager we brought
the soundmanager
across from Mac OS 8 & 9 to help make
your jobs a lot easier it's callable
both from CFM and ma co which makes it
really nice since you can create a CFM
app that uses the carbon sound manager
that for the most part with no real
changes at all will run on 8 & 9 and it
will also run on Mac OS 10 it's also
accessible from carbon and cocoa so
cocoa has its own in a sound class but
if for some reason you already have
carbon sound manager code or you need a
little bit more control than an S sound
gives you what have you you can actually
call it from cocoa that works just fine
well one of the new things we've added
as far as Mac OS 10 is though the carbon
salmon directly now supports variable
bitrate decoding that's a big issue for
mp3s and things like that where they
start to try to actually vary the
bitrate to improve the compression that
you get with your sounds however we have
had to remove several api's for one
reason or another probably the biggest
one that we've heard people complain
about are the sound play double buffer a
number of people were using that one to
do a real easy you know ping-pong back
and forth between sent to sound buffers
that one is no longer present in the
carbon sound manager and in order to
help you for those of you that we're
using that API we've got a very good
sample called the carbon sound play
double buffer and encourage you to check
that out it's on the sample code website
that developer.apple.com slash sample
code probably under the sound section
there it's a pretty good sample it
explains how to use the carbon sound
manager and some other API to do pretty
much the same thing that carbon or that
the sound kway double buffer did before
we've also removed some of the disk
based api's the ones that played
directly from a file and things like
that
and wavetable synthesis is no longer
there for an example
for the really curious among you there's
some other changes under the hood
between macros 89 and Mac OS 10 that
your app probably shouldn't care about
but I thought I'd mention them for those
of you that are interested on Mac OS 8
and 9 the sound manager was this big
global thing and it was actually only
one on the whole system and the hardware
model was provided by the sound manager
itself it had to know about all the
different sound hardware on every single
machine and figure out what machine you
were running on and do the right thing
on Mac OS 10 however the sound managers
process and in talking to the audio guys
shouldn't make any difference to your
app pretty much or either changing you
know say the volume on a sound channel
which is local to your app or you're
changing the global volume which is
still global so you shouldn't really
care about that one either
another interesting point is the
hardware model on Mac OS 10 the carbon
sound manager is actually a layer on top
of core audio so that will introduce a
slight performance hit perhaps but again
your app shouldn't really make you know
care one way or the other so I thought
I'd step through just real briefly for
those that haven't seen the carbon sound
manager want to know what it looks like
we can step through a little bit of code
really just a few slides here so one
important thing you need to have if
you're using the buffer and callback
scheme is you need a sound callback and
prototype that up there at the top it
takes the sound channel parameter and
the sound command and then when you
actually want to create a channel the
channel is the thing that you actually
send your sound commands to to play your
buffers you pass it a pointer to a sound
channel you pass it in this case we're
telling it we want to send sampled sound
we want a stereo Channel and then we
pass in that callback when you get ready
to play a sound you need to tell the
sound manager what format that sound is
them and so in this case we're filling
out a header structure then these are
just some of the interesting parameters
you have a pointer to the sound data
you're playing how many channels are in
that sound
the sample rate and we also tell if this
is an extended sound header which lets
you do some additional things you can
set the base frequency I think number of
frames isn't an extended sound manager
thing samples per buffer and sample size
so we're playing 16-bit stereo 44
kilohertz sound in this case so once
you've got the channel set up and you've
got the header set up you'd actually
send those commands to the sound Channel
and the first block of code there we set
up what's called a buffer command so the
buffer command simply tells the sound
manager here's a block of sound data
that I want you to play and we pass the
header appointed to the header that
we've just created that describes and
detail the format of the sound and we
pass that to the sound Channel with the
sound Duke command the second block of
code there let me just get through these
in order to know when that buffer of
sound is completed so that you can cue
up the next buffer of sound you can pass
in a callback command and I believe we
have a bunch of sample to do this
QuickTime does this kind of sound
playing you pass in a callback command
the parameters don't really matter and
you pass that to the sound channel
through much the same as you did before
now one interesting thing to note and
this confused me at first when I first
started looking at this API you you're
giving it a callback command but you're
not telling it what to call back and if
you remember we actually passed that in
when we created the channel so that's
one sound callback is set per channel
it's not per callback command so you
have to have all your callbacks on a
particular channel go through one one
actual callback function and then once
you're done with the channel and after
you send a number of buffers played
whatever you want to don't forget to
dispose it
so moving on to quick time I'll put in a
little plug for quick time here since
this is a game session quick time is
really good for complicated sound data
like mp3s and midis they do all the
heavy lifting for you but it's also
really good for still image looking
anybody that saw Jeff's 2d high
performance to do OpenGL talk he uses
QuickTime to do the image loading so he
doesn't care what format it's in he just
says QuickTime let me you know load in
this image whatever format jpg BMP you
know PNG whatever and QuickTime does all
that work for and puts it into a buffer
then he can hand that directly to OpenGL
as a texture so it's really good for
that it's especially good way to get
some things prototyped and up and
running if you want to do your own
graphic format later you can but at
least to get you started
quick times a great way to get started
and of course will be playing time is
famous for that but I thought I'd throw
it on there anyway so as promised here's
a one page mp3 player to get QuickTime
started enter movies and in this case
we've passed it in a file spec of the
file we want to play and in my demo code
that I'll show you in a minute
we actually just use nap services get us
a file pass it in here we open the movie
file say create a movie from the file
and that will give us for that ref numb
then we get out of open movie file it
will give us a movie the structure fill
out the movie structure that we can pass
to the other api's and then to play it
really simple we start the movie as long
as movies not done we call movies tasks
then when we're done we dispose the
movie close the movie file and exit
movies we're done so all it takes to
play an mp3 really simple stuff I'll
prove it
so we go to the demo to machine this is
a real simple app essentially the carbon
basic carbon template from project
builder through and pretty much that
code you saw there
[Music]
easy stuff now there are some more
in-depth samples on our website again
for how to play mp3s if you want some
more control over how its decoded and
how it's played check out our sample
code side I know there's some that more
directly use the carbon sound manager
and QuickTime together to play some more
detailed things let's go back to the
slides thank you let's talk about the
new guy for audio so the number of core
ideas sessions I think one has already
occurred and two more coming up I'll
tell you about them in a little bit but
I wanted to go over kind of a high-level
look at core audio so that you could get
a feel for what it is and whether you
should be looking at it for your game so
choreo is a pretty low level interface
provides a number of capabilities built
into the architecture some of these are
ready to go now some of them haven't
been exposed yet but for one audio
device sharing of course you want to
make it easy for different devices to
share different processes to share the
same device if you have say an mp3
player playing and your game comes up
and wants to be playing audio and then
the system wants to beep to tell you
something important happens everything
has to be able to share it in the
example code that I'll show you in a bit
we just pretty much asked for audio for
the default output device we say
whatever you know sound goes to by
default that's cool for us there are
other calls that you can use to get more
interesting info actually get a list of
the different audio devices available
things like that kirara also provides
some facilities for real-time audio
inter-process communication and that
would essentially let multiple processes
sort of pipe audio data between them so
if you had one app that was generating
some audio and another thing you wanted
to send it to say an app that was
recording that in some format or
whatever you could actually chain them
together and that's on a processed basis
they also have a lower level what they
call the audio unit and component model
where you can actually have audio
processing units and string them
together within your app so you might in
your app create the reverb unit
and you know some other units together
chain them together and then start
sending audio through it one of the
other interesting things about quality o
is it's designed with low latency and
it's supposed to be able to handle
really well wait and see and also
synchronize output between different
sounds and a one interesting note there
is you can actually control for the most
part the latency in your app unlike the
sound manager with core audio you can
actually set for a given device what you
want the buffer size to be and on nine
there was always a big problem between
VM on and VM off for games and the
carbon sound manager are actually just
the regular sound manager with VM on the
system would make the buffer much bigger
and so if you decided to change what you
were playing you'd have to wait for that
buffer to complete before the next
buffer got going on core audio on Mac OS
10 that's not a problem you can set the
buffer as big or small as you want now
one got chip with core audio is the
quality uses floating-point samples now
that does greatly simplify your
application code especially in the demo
I'll show you we're denim generating
tones and things like that
it's really easy to generate but doesn't
make the drivers work a little bit
harder because the existing hardware we
have right now sends integer data to the
cards also if you're coming from say a
conversion where you have wave sounds of
some things like that coming from
Windows or some other platform that are
8 or 16-bit integers you're probably
going to have to convert your code
convert your samples as on-the-fly or
you can pre convert them and store them
on disk in floating point samples one
thing is that altivec will really help
you there
I understand there's a Veck CTF function
that can do integer to float conversions
very quickly you need to watch out for
alignment issues there since altivec
wants to deal in 16 byte chunks of data
you don't want to make altivec do extra
work too
so in the carbon sale manager you got
sound samples into the system using the
buffer commands and the callback so that
was your basic mechanism for getting
sound into that system with core audio
you deal with these things called i/o
procs and so for a given device you can
install one or more IO prongs and your
i/o procs when they get called get a
number of very interesting parameters
they get a number of timestamps as I
mentioned core audio was designed so
that you could actually synchronize
audio well if you're gonna synchronize
audio you need to know a lot of stuff
like what time is it now as far as the
sound system is concerned and when are
you gonna play this sound that I'm
getting ready to hand you you know
you've asked me to fill this buffer
when's that buffer actually gonna get
played so you get that information
you'll get some info input buffers back
as the name implies it's both input and
output brock so you get some input
buffers if the device is actually
needing to send you data that's where
that will come in and then there's a
chunk of output buffers that you can use
to put your samples in and send the data
out to the card now last bullet there if
you need to know what the stream is like
you need to know how many channels or
sample rate and those kinds of things
you can actually make a call to get the
que audio device property stream
configuration you have another API with
really long name names you can make this
call and it'll fill out a structure for
you that will give you very detailed
information about what this i/o proc is
going to get and what the stream is like
now for the people that are really
curious we can go into how the actual
audio gets to the device for each device
on the system there's one real-time mock
thread that's pretty high priority and
it goes it takes care of actually
calling all the i/o procs
when the i/o needs to when the system
needs to move stuff back and forth and
the sensor that device starts that
thread up with the first i/o proc you
install as soon as you activate the
device with the first i/o proc the
device is up and this threads running
and calling your I Oprah
and the threat stays running until you
actually remove your last IO Croc and
then it shuts back down again so let's
look a little bit of what that thread
looks like this is some real high-level
pseudo code essentially loops until it's
done
it sleeps until it has something to do
they can tell when the next input or
output needs to happen sleeps until then
then it looks to see if the device has
input coming back into the end of the
system if it does it'll calculate
exactly when that input was sampled and
then copy that data into the input
buffers to get ready to handle the IO
procs then it says ok does the device
have output is it somebody installed on
Io proc to send data out okay well let's
calculate when that output is actually
going to be sent clear out the output
buffers to prepare for calling the IO
brock's and then call all the i/o procs
that are installed for this device as I
mentioned that even a particular process
can install more than one and you can
have multiple processes sharing a device
so there might be a number of i/o Crocs
actually installed here once it's called
all the i/o procs
you've got say a handful of i/o procs
that have filled out their buffers
somebody's got to mix them to send them
out into the output stream that's when
core audio comes along and actually
mixes all those io proc buffers together
and then it sends it out to the card and
loops back around so it spends its
entire life time just gathering the
input clearing the buffers getting the
calling I approximant sending the data
out so let's look at some code so this
is the basic idea if you're a carbon CFM
app you've got a load quality of ICF
bundle karate is not available from CFM
so there's some good sample code on the
web and our sample code site and are
actually in the carbon live SDK as well
about how to call CFM or how we call ma
KO routines from CFM once you've got
access to the core audio system you can
make some calls together device
information you can set up the device
properties the way you want them make
sure the buffer size is correct and
everything you add in your i/o proc and
then you start the device and as soon as
you start the device it starts calling
your IO proc asking for DES
so a brief diversion into the bundle
api's if you have a URL say to the core
audio bundle and this applies to any
framework bundle you can get a reference
for the bundle using CF bundle create
you load the executable for that bundle
to make sure it's in memory then you can
get a function pointer for in this case
some non-existent CA function name is
the name of the function you get a
function pointer for that using CF
bundle get function pointer for name
hardness what that does once you've got
access to that API then you need to
start calling them so you can call audio
hardware get properly and in this case
we're asking it for the default output
device and karate oh guys recommend you
actually use the default output device
unless you have a specific reason not to
if you want to actually look at the
api's and query for the different output
devices you can but this one will real
easy way to just tell you okay what's
the basic output device that I need to
use this will give you an output device
ID from there you can get and set some
properties on it as I mentioned before
you could get the configuration for the
stream and things in this case all we
need to do is we just want to say we
need K samples per buffer and each
sample is a float so we set that buffer
size in there I don't even remember what
I used in my code then we have to
install our i/o proc and the i/o proc is
actually it's actually mostly input
parameters the top two thirds there's
the parameter list and as you can see
you get a device ID so you can actually
have the same proc installed on multiple
devices so this will tell you which
device is actually asking for data you
get the timestamp for the up from the
audio system to say here's what time it
is now the input data and the input
timestamp when that data was actually
sampled then you have the ones that I've
highlighted there that are more
interesting for our discussion the
output data the time when that data is
actually going to be played and some
client data that you could actually pass
in when you install the i/o proc and
then down there at the bottom I put just
a real simple you know for each sample
frame you know a frame being left and
stereo whatever for each sample frame
for each Channel neither the left
channel the right channel fill in that
output data buffer there once you've got
your i/o proc installed all you have to
do is start the device so you say start
the device with that i/o proc a caveat
here as soon as you call this it's going
to start calling your i/o proc so beware
make sure that you don't do this and
then expect to be able to set up a few
more structures or whatever for the i/o
proc it's already going to call you so
be ready for it so let's take a look at
a simple demo here and my colleagues
have voted this the most annoying demo
at WWDC so I'll show you the simple tone
demo so this is a simple cocoa app
that wired up and not too long big plug
for Coco here really easy stuff to play
with good for prototyping and user
interface
[Laughter]
[Music]
sine waves you can also play with
if you get them halfway out of phase
[Music]
so that's the nice version
that one has nice simple octaves and
everything let's run this one this one
we can play a little bit more with some
other things you learned in music theory
class
[Music]
so all I'm doing here is simply got a
KOCO app I've installed four different
IO props one for each channel and the
core audio is taken care of actually
calling these back for each one in turn
I'm simply generating the waveform on
the fly sine waves square wave thought
to
fairly easy stuff we'll be posting the
sample code in the next week probably so
you can take a look
doesn't work and how to
how to use for audio get to those
especially for those of you that work in
cubes I was actually working on that app
a little bit during Jeff's OpenGL
earlybird session and people were
leaving okay so to wrap this up real
quick high-level you know we've talked
about several different interfaces core
audio and sound managers are great if
you've got raw sound samples that you
just want to throw out get out to the
card to play them if you've got
something more complicated like MIDI or
mp3 it quick times a really easy way to
get that up and running take a look at
the API it's really simple if you want
to do the heavy lifting you can but cook
time Marty has done an awful lot of work
to get that nice and neat so you might
want to take a look at QuickTime API and
coming up actually luckily there's still
two audio sessions coming up in this
very room at 3:30 we've got the audio
processing in sequencing services and
then for those of you that are more
interested in some of the more powerful
MIDI services that Mac os10 provides at
five o'clock in this room we've got 210
MIDI on Mac OS 10 and then since this is
a game session if you have games
feedback for us if we're doing something
well if we're not doing something well
if there's something you'd like to see
more of or less of what have you please
come to the feedback forum in jae-won
which is next door and give us our games
feedback on games technologies and
that's it for my part now I'll turn it
over to Todd
thank you he wasn't kidding about those
demos was he hi my name's Tod Previn I'm
the 3d graphics and de facto networking
DTS engineer so I'm gonna recap one of
the things that David wanted David
slides went over which is what we're
gonna learn about networking today I'm
gonna go through bsd sockets in the most
most detail including accessing it from
both CFM and carbon and from from cocoa
then I'm going to go through some simple
setup and initialization code I'm also
going to discuss some of the networking
technologies that are available on 10
that are better suited to gaming as
opposed to things like URL access which
is more designed for mainstream
applications let me go through some tips
and tricks for networked gaming that's
kind of a misnomer it's more of a it's
more like a porting guide kind of give
you some idea of how things map over to
10 so what do we have for networking on
10 well that first of all carbon there's
carbon open transport as that name would
imply open transport has been carbonized
for OS 10 it's all there all the
functionality that you need and that is
one of the options you can use Nets
Brocket open play we've gotten a lot of
questions about this very recently and
nets brachot and open play are now also
available on Mac OS 10 and of course
there's sockets which is available in
the BSD layer so open transports
available on 10 mainly as an easy path
for existing applications to move over
to Mac OS 10 from OS 8 and 9 again as I
said all of the functionality of OS 9 is
there so you don't have to worry about
what what are the differences the whole
thing has been taken and just pulled
right over directly the open transport
frameworks are all built on top of
sockets now as opposed to whichever
underlying layer they used on nine
I don't know offhand
this has been included for api
compatibility only there's no additional
functionality that you get from open
transport on Mac OS 10 open transport
uses threads to emulate any of the
asynchronous mode stuff that was
available on OS 9 you do a you do incur
about a 10% performance hit for using
open transport as opposed to using
sockets directly and the protocol subset
that is supported by open transport on
10 is much smaller than it was on 9
supporting only tcp/ip DDP IP and n n BP
for appletalk open play net sprocket is
a derivative Wilander but it's the
evolution of net sprocket from
traditional mac OS apple open sourced at
some time back and since then it's kind
of developed into two different areas
that being open play and that's Brocket
itself they're both open source api's
they are now cross-platform available
Mac and Windows I believe there was a
Linux UNIX version that was supposed to
be coming but I couldn't find much
information on that and it also has been
carbonized for Mac OS 10
so with Nets bracha what they did was
they made it the high level interface
that is now instead of built on top of
open transport I believe is what Nets
Brockie used to be based on it now sits
on top of their own API which is open
plain which I'll discuss in just a few
minutes it does maintain most of the api
compatibility with net sprocket although
as i understand are some there are some
differences between the two no new
documentation is available for net
sprocket but you can still use the won
7-3 I believe is the current version of
Nets bracket documentation that is
available that is still the most current
so what exactly is open play open play
is the low level interface that they've
developed for for use on both Windows
and Macintosh it's sort of akin to
sprockets or rock excuse me sort of akin
to sockets in that it doesn't have a lot
of there's not a lot of one of these
days I'll think of the words that I'm
trying to come up with here it's it's
it's fairly streamlined fairly simple
and there's there's just not a lot
there's not a lot to it
as far as being overly friendly with a
user interface they left most of that
functionality up to Nets Brocket it's
been called a network module manager so
what exactly is a network module manager
it's a protocol manager you tell it
which protocols you want to use and and
what you want to do with them it sets
them up and then you can access them
either directly through the open play
calls or you can go through the high
level net sprocket interface and access
them that way so it provides three basic
services which is configuration data
transfer and enumeration now in the
documentation it says it also provides
human interface and miscellaneous
functions but neither one of those I
could find a whole lot of information on
I think the user the human interface
they're referring to was net sprocket
but again couldn't find much out on that
configuration wise just as I said it'll
set up the protocol stacks for you you
can do all your initialization right
through open play just as you can
through sockets data transfer it's what
communicates with the drivers with all
the network drivers sends it down to the
hardware and spits it out on the wire an
enumeration it will go through all of
the available network interfaces
including any sort of serial dial-up or
Ethernet interfaces it will do numerate
them for you so you can select whichever
one you want to use this is kind of a
graphical representation of how open
play and nets Brockett function together
with the high level interface sitting on
top of a
the network module manager and the
network module manager calling down into
the various various protocol stacks and
and device interfaces that are available
there's a little more information on on
open play but URL is for apples open
source open source website you can
access it right there there is a
complete set of documentation well ok
not exactly complete but there is a set
of documentation that goes along with
open play it's it is really downloadable
right now I believe the version is 2.0 a
or something like that is the most
recent one that's been posted up there
and if there is there are two sample
apps I believe mini play and mini test
are the two apps that I saw in there
that I was that that I was able to look
at they again it's all been carbonized
so they should all just build and
compile right out of the box this is
gonna be the real meat of our discussion
here which is BSD sockets it is the
standard UNIX networking API it's
available across every implementation of
Unix out there the interface itself has
not changed in many many years however
there have been been some super sets of
it made for for like Windows and I
thought SGI and with I ryx had another
had another implementation of sockets
that had more of a higher-level user
interface to it then then straight
sockets did but one of the key things
about sockets is that all of the
functions are synchronous they are
blocking calls so anytime you actually
call one of these things you're gonna
have to wait until it completes as
you'll see you later on with certain
functions such as DNS when you do get
hosts by name or get host by address
you're gonna sit there waiting for a
while if you've got some slow DNS
servers in your pathway this is sort of
how a socket application will look from
a high level both the server and client
will both call socket to create sockets
for themselves sockets are just file
descriptors is really all they are
across any operating system so they're
pretty much going to function the same
way any anytime your act
some sockets for a server it's important
to call bind what mine does is bind
takes a local the local address of the
server and associates it with that
socket so that any incoming connections
to that server will say oh here's the
server we're looking for here's the
address I want you're the one and that's
how they that's how a client-server can
establish an association the server
woman call listen as listen is what sets
up the socket so that will accept
incoming connections and that it would
be on the client side the reference for
that would be connect where the client
actually goes out over the network and
says alright this is the server I'm
looking for where are you the server
that's now in listen mode will hear hear
that incoming connection and and then
provided of course that the the
connection is is correct and the server
is set up to handle a connection from
that particular client it will call
accept accept basically tells the server
that yes or excuse me
accept is the service way of saying
alright you client you're good to go
I'll accept your connection accept will
create as it's returned value it creates
a new socket in a connection-oriented
mode it it would actually create a new
socket that is the that is now
associated with that with that end of
the with with the incoming clients
socket so you've now got a endpoint to
endpoint connection once you've
established that association between
those two sockets you're now free to
send and receive data back and forth
between client and server when you're
done once once all the data has been
transmitted that needs to be transmitted
both sides call close to to get rid of
the socket or excuse me to close the
that will close the connection that will
not destroy the socket yeah how you do
that I'll show you in a moment so how we
can initialize the socket interface
well CFM Carbon applications are going
to need to call are going to need to
load the system framework the sockets
framework through CF bundle David showed
you had to do that in the sound portion
I've also included a URL up here at the
bottom of the page that if you look for
the sample call ma Co framework that
will tell you how to
a CF bundle or scuse me load amok Oh
framework from a carbon CFM application
ma Co carbon applications all you have
to do is include the system framework
and it's right in there if you wanted
access to the actual if you wanted to
see what the header files actually look
like they're in the cysts subfolder of
the system framework and there's Sakai
Oh socket SH and suck at VAR h are the
three header files that you're going to
want to look at mainly if you're if
you're curious
Co Co applications have two options
naturally you can use the NS sockets
framework or you can load the system
framework and access them directly as I
just described either way works just as
well the NS sockets framework I believe
is obviously set up for an objective-c
interface so it's it's really six of one
half dozen together depending on which
one you want to use so creating sockets
as I mentioned before each both servers
and clients will need to create sockets
in order to communicate over the network
per connection you you need one socket
now with with multi casting multihoming
and a couple of the other couple of
things like UDP for instance you can
actually because it's a connectionless
protocol UDP is is capable of sending
messages to different hosts on the
network for instance of the UDP if you
had four servers out there and one
client if all of them were using UDP the
client would be able to send a message
to server one server to server three and
server flow without establishing a
connection in between all of them
because UDP is a connectionless protocol
uses what's called a Datagram that
includes in it the core as a parameter
to the send function or send to function
it includes the address of the server
that you want to talk to or the the
destination that you want to talk to so
every time you send a message you're
telling okay I'm sending this one to
server one now I'm gonna send this one
to server for that's already included
right there in the in the sent to
function the functions of the the socket
function returns the socket descriptor
as as I mentioned earlier the sockets
descriptor is just a file descriptor if
you really look at it it's just an int
so
very simple datatype so how you gonna
create sockets this is a little this
code here can be you you can use this
code directly and you'll create sockets
of various types the top one is a sock
stream that's used with the protocol tcp
which will create a connection-oriented
data stream oriented socket these are
useful for things like doing file
transfers if you're going to send
contiguous blocks of data so if you
wanted to do if you wanted to stream if
you wanted to stream audio out you
probably want to use TCP tcp is a
reliable protocol which means it does
it's error checking and correcting it
will do resends there is a little caveat
to that tcp is under no obligation
whatsoever to let you know that it's
doing resent or let you know that it's
dropped packets so what does that mean
well you can be sending your data
happily to a TCP socket and it will be
humming along just fine the other end
won't be receiving any of it you won't
know about it and neither will they all
they see is no more data is coming
through TCP will just stop that's it
it's all you get so there's really no
way to to make tcp/ip or if should be
TCP tell you that it's it's now doing
error checking and correcting and trying
to reestablish its connection there's no
there's no functionality for that
whatsoever
which means it can be kind of dangerous
to use if you if you have real time
critical data so what's your option UDP
UDP is connectionless but it is
unreliable what you have to do is
implement a reliability protocol on top
of UDP fairly easy to do all you have to
do is as you're sending messages back
and forth you just make sure that both
the client and server have some method
of saying all right I send a message did
you get it client responds I got the
message so and then you just kind of
loop back and forth on that whenever one
of them does not receive a message all
you have to do is say alright resend and
yuri transmit the same data does require
a little bit of work although most of
the time if you're if you're talking
about the network gaming or where you
really need to be sending data back and
forth
it doesn't matter if you miss message
five and you're now on message eleven
message five is probably irrelevant
out-of-date information anyway so
there's no need to resend you drop it
you interpolate between where you were
and where you are and you move on for
instant the last thing is an ICMP which
is Internet control message protocol you
would use this for any sort of well
Internet control message things like
pings
pings are all done through ICMP so
establishing connections well the first
thing you need is you need a an address
and sockets defines the sock a DDR
structure which has a name it's got a
port and an address those are the three
things that you need to establish the
association that you need for a
connection that applies to both TCP
connection oriented and UDP
connectionless associations generally
speaking you're going to need the length
- which is why you do the size of the
address just for for the purposes of
sending it to some of the some of the
initialization and sending functions
that sockets has you'll see int backlog
that's used down there on the listen
function where when the server calls
listen on a particular socket it needs
to know how many connections you want to
queue before it starts dropping them if
if you specify that to zero it will
process connections as they come in
there's only one problem with that in is
that if you're processing a connection
if you're in the middle of processing
and connection then it's not going to be
paying attention to what's going on on
that socket so it connects you come in
and it will just automatically drop so
generally you want to set it to
something like two or three if you have
an extremely busy server you want to set
that up higher so it will actually queue
the connections up and you don't lose
any of them bind right above it what
bind does is is it will associate the
socket address
that you've specified with the socket so
for a server what does that mean as I
said before it means that now the server
has an idea of who it is so when there's
connections coming in to that specific
address the server knows that it's
referring to itself and will then
continue to call it it will it will
continue to accept incoming connections
because it now has some identity now you
can call bind on the client-side that's
useful for a couple of different things
if you have a UDP connection that's
connection it's it's UDP connectionless
association on a client-side it's kind
of strange because a UDP socket will
accept input from anywhere so some
random guy on the net sends a package
out that happens to have or sends a
Datagram out that happens to have your
address in it because they erroneously
specified it unless you're locked in
your your clients gonna gonna pick that
up and it's gonna read that data in
society prevent that from happening what
you call bind what bind does in the
client-side is it says all right I'm
only going to use the socket to transmit
data to and from this address it will
not accept data from anywhere else it
will only accept datagrams from the
address that you specify this does not
mean that you cannot reassociate that
socket later if you need if if for
instance your client wants to
communicate with a couple of different
servers there's a little more work
involved you have to actually shut down
the connection and destroy the
association recreate your socket and
then continue to send or continue to
communicate with the new server but it
can be done
so again onto the accept function this
is only used on the server side it can
be used when you're talking about a
client-server architecture if you have a
client that is also a server you can use
accept although it's usually easier if
you're doing client-server to just go
peer-to-peer as opposed to having the
the two separation there if you don't
call accept excuse me if you call accept
from a server it will create a new
socket so now you're gonna have a wider
array what you would end up with is
you'd end up with a whole bunch of
sockets that are associated with the
same client so you'd kind of get this
criss-crossed network that ends up being
you'd end up with peer-to-peer at that
point so sockets she's me except takes
the sockets do you want to accept the
incoming the incoming connection on it
accepts it also takes the address and
the address link it will have that
information because when the server
receives the incoming connection from
the client the connection the the
incoming address from the client is
actually transmitted to the server
that's where you will get that
information from now when the accept
function returns it does return a new
socket if you want to communicate with
the client on the other end of that
socket that is the that is the socket
that you use the listening socket on the
server you shouldn't be transmitting
more data on because it's sitting there
just waiting for incoming connections so
here we'll go through the connect
function this is again for connection
oriented for UDP it's slightly different
the socket that you pass in there is
there is the clients local socket the
address that you pass in is the address
that you want to connect to not the
address of the client I suppose you
could connect to yourself if you wanted
to do a loopback but yeah that's that
would be entirely application-specific
you also send it as I mentioned earlier
the address link this is one of those
functions that requires that needs to
know how much data you're actually
passing into it connect only returns
Connect does not return anything
error codes it will return zero if if no
errors you can use last error I believe
will give you the last socket error that
occurred you have to be careful that
because that's not updated it's only
updated when an error occurs so if you
call get last error if when you when a
function returns zero you'll get the
last error that actually occurred what a
little caveats about connect is that
connect assigns the local address if you
don't call bind normally that's fine
unless you wanted to assign your client
a different address there wouldn't be
much of a problem with that the reason
that it doesn't do this I believe is for
when you want it to do dynamic address
updating that's getting way way off
off-topic that's not something I want to
go into so sending receive data you've
got a couple of different functions for
connection oriented sockets you'll be
using send and receive there's also two
other functions that are sent to and
receive from those are mainly used with
UDP because they one of their parameters
is the address that you want to
communicate to or from with a
connection-oriented socket both
functions perform identically there's no
there's no difference you're simply
passing in an address but you've already
got a connection the connections
establish is already associated with
that address so the the extra input is
just discarded you can use both of them
synonymously with a connection-oriented
socket tcp streaming which is usually
not a bad idea if you're gonna be
changing protocols on the fly she'd
probably use send to and receive from
there's slightly more overhead involved
with them but it's not significant
enough to worry about
so as parameters send takes the socket
that you want to send on for a client
that would be the only socket that it
has for a server that would be the
socket you know for a for a streaming
server for a TCP server that will be the
socket that is associated with a client
you want to communicate with if you have
a wide array of clients and you want to
broadcast a message to all of them using
TCP you'd have to
right through each socket and send the
same data on each socket before you
could move on
it also takes above a pointer to a
buffer which is just a buffer of bytes
that it will read in and splatter out on
the network bytes is the byte count
that's how many that's how many bytes of
data are in the buffer at the time and
you just you pass that along along with
any flags that you might have flags are
not terribly important they really only
if you're gonna be sending things like
out of bow out of band data which is
beyond the scope of this discussion is
is flags really important most of the
time you can just pass zero receive on
the other hand is the sockets you want
to receive the data on again for a
server you're gonna have to iterate
through all of the all of the sockets
that you've created with accept in order
to get all of the data that's incoming
from the clients which would be kind of
slow this is why it's recommended that
for for real time like games for
real-time data like that you want to use
UDP it gives the server one socket that
it has to read data in on granted the
buffer is large but you can read data in
a lot faster from a single large buffer
than you can from 300 buffers having to
loop through each one and call the same
data input routines every time receive
takes the same number of parameters
widths and the same kinds of parameters
as as send the receive buffer however is
not a pointer to the buffer that the
data is in it is a pointer to the buffer
that the data will be transferred into
if you do not have a data buffer that is
large enough to accommodate the data
this function will fail it will come
back with the forget the the error
message that it fails with but it fails
with with something similar to your data
buffers not big enough so reallocate it
to get around that you can do a if you
pass in as one of the flags is one of
the flags to receive I think you can
pass in message peak which will tell you
exactly how much data is in the buffer
so you can do that before you read it in
every time and allocate your buffer
dynamically like that
so shutdown and cleanup
all these functions take will close
close just shuts down the socket that's
all it does
and it just except it only takes as a
parameter the the socket that you want
to close very simple shut down on the
other hand is a little more in-depth
shut down with shut down you can tell it
what you want to do with any residual
data that's remaining on the send to
receive buffers a lot of times you'll
want to flush and clear any residual
data you want to get those last few
bytes in or out so you want to use shut
down a lot of times the extra control
that that shutdown does offer is quite
useful and I actually will call I call
shut down in my network applications
more more often than I just simply call
closed your port number is going to be
assigned based on on your address so but
both of them are actually in a clear
port once the socket it once the socket
is closed or shut down that will that
will free the port so a few little tips
and tricks for Mac OS 10 for open
transport applications what can you do I
know there's a lot of existing open
transport applications out there so
there's there's two options you can use
the OT shim that's there it does work
but your other option is to port it
directly sockets as I said ot on ten
sits right on top of the sockets layer
and you do incur about a 10 percent
performance hit to use OT as opposed to
going directly to sockets I'm gonna go
through a couple of slides in a moment
that will show you how ot maps maps to
sockets if in fact you do want to port
your OT app to two sockets directly for
Windows UNIX applications UNIX apps are
going to be pretty much a
straightforward port I don't think
there's any semantic differences between
our implementation of sockets and the
standard UNIX implementation windsock
applications there are some notable
differences which I will which I will go
through momentarily and there's also
direct play applications which aren't
going to really translate across to
anything
give you some suggestions as to where
you might want to look so using your to
Sheamus again the easy way onto nine or
from eight and nine onto ten reporting
two sockets would be my my
recommendation so how are you going to
do that well here's some of the on the
left-hand side of this of this slide
you'll see some of the some of the open
transport functions on the right you'll
see they're they're sort of a brother
over that it lives in sockets land so T
end point that's just a socket as far as
as far as we're concerned here bind and
connect map over to binding connect of
four sockets for an active ot connection
now I'm not exactly sure what the
difference is I'm not really an OT guy
but these two obviously map pretty well
right over - right / two sockets so for
sending data again there's there's an
extra sin which is send message which is
Datagram oriented that's a function call
that I'm not too familiar with I tend to
stick to send and send to myself but I'm
assuming that they're going to be fairly
simple and probably something more
similar to send to then then it would be
to send that is they take the address
parameter and I'll take a probably the
length of the address I would assume and
receiving it's the same way
so disconnecting and cleaning up as I
said you can use shut down
what are interesting things about this
is the set saw cop so linger what
exactly does that do
setting that sock option s olinger means
that the socket is going to stick around
until you actively close it and until
any remaining data is read or received
from that socket mr. Stahl it means as
opposed to if you simply called shut
down or or close you can actually just
kill it right there and not read any of
the data in so I mentioned before know
something about synchronous operations
these two functions get hosts by name
and get hosts by address
they're both blocking functions which
means that they're going to stall until
they actually get a return there's a way
around that which is by placing these in
their own threads and letting a thread
go off and wait however long it wants to
while you continue with your application
that's the recommended way of emulating
async mode on Mac OS 10 or on any socket
supplementation for that matter another
point to note about these is you can't
cancel them so once you go in there's no
going back
you gotta wait till it finishes
so with direct play direct play is
obviously specific to Windows directly
there's no there's no other API like it
out there safe or something like a net
sprocket that is kind of the high same
high level type API you can port direct
play to net sprocket I'll be perfectly
honest with you I have never looked into
doing that
so I don't know how much work would be
involved but I would assume that it's
probably not going to be the easiest
thing to do but it is an option if
you're willing to go down that path
windsock is much more interesting
windsock mostly maps onto sockets
directly by mostly I mean that there are
some functions in windsock that are
specific to where to windsock itself so
what are the differences sockets has no
a psychic or asynchronous functionality
I just mentioned before how to how to
deal with that little caveat there are
also no predefined startup or shutdown
routines because they're not necessary
in Mac OS 10 or on any sockets
implementation aside from Windows I
believe like WS a startup W say cleanup
W say async select is another one that's
used a lot to generate the asynchronous
message modes that windsock uses none of
these things are available because they
are they are not part of the standard
sockets excuse me standard socket API
which is the standard cross-platform
sockets API they are only available on
on Windows any functions that are
prefixed by the WUSA those are all
specific to to Windows itself so if
you're looking for cross-platform
compatibility those are things that
you'll want to try to use less the last
bullet on this slide is is kind of kind
of interesting Windows defines a data
type of socket all uppercase the
standard socket data type is just an
integer so it's file descriptor so why
does Windows redefine the socket that's
a good question because I don't rightly
know
I do know that it causes a lot of
problems oke because when I was first
writing network applications I was using
the socket data type very heavily until
I found out that you can just cast an
int to the same thing and it still works
yet I don't have to go through the
effort of recoding every time I move my
windows code to another platform so just
one of those little interesting tidbits
I stay away from the socket definition
so kind of as a summary I went through
the networking technologies that are
available on Mac OS 10 those include
open transport which is fully carbonized
open plain Nets Brocket again which are
which are carbonized and are also open
source and I also went through sockets
in some in relative detail I went
through the initialization of it and how
to set up your sockets application and
kind of give you a general idea of how a
client-server application is going to
work went through some of the little
little tips tricks and caveats for
networking on Mac OS 10 and bringing
your network applications to OS 10 and
one of the more important things was
illustrating the differences between an
API such as windsock that is specific to
the Windows platform and the sockets API
which is a standard UNIX definition so
for a little more information on
networking there's there's two series of
books that I would highly recommend to
anybody who's very interested in
networking the top one is UNIX network
programming by Stevens excellent series
of books the first one the Volume one
goes into a lot of detail about how the
networking subsystem operates on UNIX it
goes into the whole basis for for tcp/ip
and there's a lot of great information
in it volume 2 is more about inter
process communication which is using
using sockets for using sockets as pipes
for talking between applications on the
same server or on different servers the
tcp/ip series it's called internet
working with tcp/ip by comer is another
great series on networking the first one
is the principles and practices the
second one is anybody now I don't
remember
I should remember what two and three are
but they're really good I know that
because I own them all there's also some
things that some mailing lists that one
escape me for a moment
there's three-minute through mailing
lists in particular at Apple that are
they're maintained on at Apple that
you'll want to look at if you're
interested more networking stuff the UM
play developers list that one obviously
relates specifically to open play and
that open source project not terribly
active but it seems to be generating
more interest now the open transport
developers list am not sure how active
that is as I said I'm not really an open
transport guy but from what I understand
it's still pretty busy and then there's
also the Darwin developers list make
sure you have a lot of room on your hard
drive if you're downloading this list
because it is busy probably on the order
of 100 messages a day but that's where a
lot of the kernel level networking stuff
gets discussed if you really want to
delve that deeply into it so my roadmap
well it's not really a roadmap because
it refers to everything that happened in
the beginning of the week but I put it
up here just for anybody who wants to
reference the sessions once the DVDs
finally come out 300 was the networking
overview you might recognize some of the
content from one or two of my slides
from the 300 session it kind of we kind
of had the same things there extensible
kernel networking services again that's
gonna be more for people who are
interested in the Darwin development
stuff and the kernel level stuff
networking configuration mobility that's
more user level network configuration as
opposed to programmatic network
configuration network services location
I don't remember what that one was about
no check it out on the DVD somebody let
me know and AFP is 3.0 and Apple shares
just that say FP on on Mac OS 10
you