Socket: 2 Simple Example

Up: GEOS SDK TechDocs| Up | Prev: 1 Introduction | Next: 3 Addresses

The sample application Appl/SDK_C/Talk provides an example of a simple application using the Socket library.

To understand how the program works, you should, of course, look at its source code. The following is a high-level overview of what the Talk example illustrates: a simple client-server connection in which the server awaits connections, the client connects, and then the two exchange data. Note: this application assumes that the host device (the client) has already connected to the server. Remote connections are usually made through PPP or Point-to-Point Protocol. See SocketOpenDomainMedium() discussed in Hardware Ports.

The example performs the following steps:

  1. Allocate memory in which to store data.
    When sending or receiving data, you need to provide a pointer to a buffer containing the data to be sent or received. Thus, the buffer should be in a block which can either be locked down as needed or is in fixed memory. Programs often spawn a separate thread to receive data from the socket; if this thread needs to lock down a memory block in which to store the data, then make sure that the thread can lock down the memory block. See the Multithreading chapter to learn about managing threads.
    (If you follow the multi-threaded approach, be aware that when the Socket's owning thread exits, it frees the Socket. To allow a Socket to survive the exit of its thread, use SocketSetIntSocketOption() to change its owning thread.)
    For this simple example, we're using a small buffer to handle the receipt of data, so we declare it as a global variable so it resides in the application's fixed memory:
char recvBuf[16];
ctrlClass = 
  SocketGetAddressController(theAddress.SA_domain));
ctrlOb = 
  ObjInstantiate( 
    HandleOf(GeodeGetOptrNS(@AddressDialog)),
    ctrlClass);
@call ctrlOb::MSG_SOCKET_ADDRESS_CONTROL_SET_ACTION(
  ConstructOptr(0,TO_PROCESS), MSG_CTP_VALID);
@call
  GeodeGetOptrNS(@AddressDialog)::MSG_GEN_ADD_CHILD(
    ctrlOb, CCO_FIRST);
@call ctrlOb::MSG_GEN_SET_USABLE(VUM_NOW);

When the user enters an address, the following code is called. It gets the selected address from the address controller and packages it up into a form the Socket library can use.

MSG_SOCKET_ADDRESS_CONTROL_GET_ADDRESSES returns a chunk with raw address data based on the address entered by the user. SocketResolve() reduces this raw address data to a primitive form that can be used for making connections.

adArray = @call ctrlOb::MSG_SOCKET_ADDRESS_CONTROL_GET_ADDRESSES();
address1 = ChunkArrayElementToPtrHandles(
  HandleOf(ctrlOb), adArray, 0,0);
theAddress.SA_addressSize = 
  SocketResolve(
    theAddress.SA_domain, (byte *)&address1[1],
    address1->SACA_opaqueSize, addressBuffer,
    MAX_ADDRESS_SIZE);
LMemFreeHandles(HandleOf(ctrlOb), adArray);
dataSocket = SocketCreate(SDT_STREAM);
SocketConnect(
  dataSocket, (SocketAddress *) &theAddress,
  SOCKET_NO_TIMEOUT);

There are two "sockets" created on this, the server side of the connection. The first socket is bound to a particular port, and "listens" for incoming connections. It is possible to accept more than one connection over the listening socket--each accepted connection is represented by another socket to represent this side of the new particular connection.

listenSocket = SocketCreate(SDT_STREAM);
SocketBind(listenSocket, theAddress.SA_port, 0);
SocketListen(listenSocket, 5);
dataSocket = SocketAccept(
  listenSocket, SOCKET_NO_TIMEOUT);
textBlock = @call
  GeodeGetOptrNS(@InText)::
  MSG_VIS_TEXT_GET_ALL_BLOCK(NullHandle);
textPtr = MemLock(textBlock);
textSize = LocalStringSize(textPtr);
SocketSend(
  dataSocket, textPtr, textSize, 0, 
  (SocketAddress *)0);
MemFree(textBlock);
while ((
  datasize = SocketRecv(
    dataSocket, recvBuf, sizeof recvBuf, 
    SOCKET_NO_TIMEOUT, 0, (SocketAddress *)0))
  != 0)
{ @call 
  GeodeGetOptrNS(@OutText)::MSG_VIS_TEXT_APPEND_PTR(
    recvBuf, datasize); }
if (listenSocket) { 
  SocketClose(listenSocket);
  listenSocket = 0; }
SocketCloseSend(dataSocket);
if (ThreadGetError() == SE_CONNECTION_CLOSED) { 
  if (listenSocket) {
    SocketClose(listenSocket);
    listenSocket = 0; }
  SocketClose(dataSocket); }

Up: GEOS SDK TechDocs| Up | Prev: 1 Introduction | Next: 3 Addresses