为什么不看MSDN,在索引IrDA里面有呀,介绍怎么用WinSock写支持IrDA的应用程序,在DDK里面也有介绍。

解决方案 »

  1.   

    MSDN里面真正介绍IrDA少的可怜!!!   我也知道WinSock支持IrDA, 但是没有具体实现细节!! 
    我的DDK是98DDK最新版本!  但是没有IrDA的有关例子!!  
      

  2.   

    偶昏...你用MSDN多少?我的是January 2000,内容也不多,可光这一页我想就能给你不少提示吧?代码都给你了,你还想多详细?如果你熟悉WinSock,你已经可以拿这些来写一个试试了。(BTW:说话最好不要那么多"!",如果你想别人帮你,回答问题的不是奴才,我不在乎你的分!)IrDA and WinSock Reference
    WSAStartup()
    Call WSAStartup before making any other IrDA calls.WORD      WSAVerReq = MAKEWORD(1,1);
    WSADATA      WSAData;if (WSAStartup(WSAVerReq, &WSAData) != 0)
    {
       // wrong winsock dlls?
    }af_irda.h
    This header file must be included by WinSock applications to support IrDA. There are several incompatible versions of af_irda.h that have been distributed with Windows CE and Windows 95 Ir3.0 DDKs and SDKs. A common af_irda.h that supports all three platforms is available with the Windows 2000 IrDA DDK, which can be accessed at the Web site www.microsoft.com/ddk/. This file may continue to evolve as the APIs of the systems grow closer together.In order to compile for one of the target platforms, one of the following must be defined:_WIN32_WINNT
    _WIN32_WCE
    _WIN32_WINDOWS socket()
    The WinSock socket() call is used to create a connection endpoint of type SOCKET. This is nothing more than an application anchor for future references to a connection. The connection is not yet established. Both clients and servers begin all communication by opening a socket.SOCKET ServSock;if ((ServSock = socket(AF_IRDA, SOCK_STREAM, 0)) == INVALID_SOCKET)
    {
       // WSAGetLastError()
    }SOCKADDR_IRDA Structure
    The following sockaddr structure is used for AF_IRDA sockets:typedef struct _SOCKADDR_IRDA
    {
       u_short   irdaAddressFamily;
       u_char   irdaDeviceID[4];
       char   irdaServiceName[25];
    } SOCKADDR_IRDA, *PSOCKADDR_IRDA, FAR *LPSOCKADDR_IRDA;irdaAddressFamily is always AF_IRDA.Server applications use the irdaServiceName field to specify their well-known service name in a bind() call. The irdaDeviceID field is ignored by the server application.Client applications fill in all fields. The irdaDeviceID is filled in with the device address of the device that the client wishes to connect() to. This address is returned from a previous discovery operation initiated by a getsockopt() call with the IRLMP_ENUMDEVICES option. The irdaServiceName field is initialized to the well-known value that the server specified in its bind() call.It is an error for an IrDA application to issue a connect() call after issuing a bind() call.bind()
    The bind() call is used by server applications to register that they with to receive incoming connections that are addressed to a specified service name on the specified socket. bind() associates a server socket with an application level address.SOCKADDR_IRDA    ServSockAddr = { AF_IRDA, 0, 0, 0, 0, "SampleIrDAService" };
    int      SizeOfSockAddr;if (bind(ServSock, (const struct sockaddr *) &ServSockAddr,
             sizeof(SOCKADDR_IRDA)) == SOCKET_ERROR)
    {
       // WSAGetLastError()
    }A WinSock bind () will cause the stack to generate a new local LSAP-SEL and to add it to the IAS database associated with the service name supplied in the SOCKADDR_IRDA.listen()
    The listen() call is used by server applications to place the stack into a mode where it will receive incoming connections on that socket. listen() does not block. The backlog parameter tells the stack how many inbound connections to accept on behalf of the application before the application is able to further process (accept()) these connections.if (listen(ServSock, 2) == SOCKET_ERROR)
    {
       // WSAGetLastError()
    }accept()
    Once a server application has put its server socket into listen mode, it calls accept() and blocks until an incoming connection is received. An unusual characteristic of accept() is that it returns a new socket. The reason for this is that the server application might need to continue accepting new inbound connections. To support this, the server typically creates a new thread to handle the new connection, then blocks again on another accept(). There is no requirement that a simple server support multiple connections, and it is free to ignore the old listening socket until it is done with the newly created socket. The SOCKADDR_IRDA passed to accept is filled in with the peer's addresses and can usually be ignored.SOCKET NewSock;while(1)
    {
       sizeofSockAddr = sizeof(SOCKADDR_IRDA);   if ((NewSock = accept(ServSock, (struct sockaddr *) &PeerSockAddr,
                   &sizeofSockAddr)) == INVALID_SOCKET)
       {
          // WSAGetLastError()
          // exit
       }   // NewSock is a connected socket.
       // Create a new thread and pass it NewSock, return to accept() on main
       // or use NewSock here until done, then close it.
    }send() and recv()
    These calls are used to transfer data. recv() will block until there is data available and send() will normally not block. send() can block if the peer is not receiving data (has stopped calling recv()). send() will unblock when the peer resumes recv()s. A recv() of length zero has the special meaning that the client has performed a graceful close on the socket. The application can assume that it has received all data that was sent by the peer. If any unrecoverable protocol error occurs during the connection, send() or recv() will return an error code and the connection will be aborted.int   BytesRead, BytesSent;
    char   Buffer[4096];// recv() example
    if ((BytesRead = recv(Sock, Buffer, sizeof(Buffer), 0)) == SOCKET_ERROR)
    {
       // WSAGetLastError()
    }
    if (BytesRead == 0)
    {
       // Peer has closed the connection and I have all the data.
       // Close the socket now.
    }// send() example
    if ((BytesSent = send(Sock, Buffer, sizeof(Buffer), 0)) == SOCKET_ERROR)
    {
       // WSAGetLastError()
    }
    // Check that BytesSent == sizeof(Buffer).closesocket()
    closesocket() initiates a graceful close on the connection and releases the socket handle.if (closesocket(Sock) == SOCKET_ERROR)
    {
       // WSAGetLastError()
    }getsockopt(,, IRLMP_ENUMDEVICES,,) and connect()
    This is the call used to run a discovery. Before a connection can be initiated, a device address must be obtained by doing a discovery operation. An extension to the WinSock getsockopt() call returns a list of all currently visible IrDA devices. A device address returned from this list is copied into a SOCKADDR_IRDA to be used by the connect() call.Discovery can be run in one of two ways. Performing a getsockopt() call with the IRLMP_ENUMDEVICES option will cause a single discovery to be run on each idle adapter. The list of discovered devices and cached devices (on active adapters) will be returned immediately. The following code demonstrates this:SOCKADDR_IRDA    DestSockAddr = { AF_IRDA, 0, 0, 0, 0, "SampleIrDAService" };#define DEVICE_LIST_LEN   10unsigned char   DevListBuff[sizeof(DEVICELIST) -
           sizeof(IRDA_DEVICE_INFO) +
           (sizeof(IRDA_DEVICE_INFO) * DEVICE_LIST_LEN)];
    int      DevListLen   = sizeof(DevListBuff);
    PDEVICELIST   pDevList   = (PDEVICELIST) &DevListBuff;pDevList->numDevice = 0;// Sock is not in connected state
    if (getsockopt(Sock, SOL_IRLMP, IRLMP_ENUMDEVICES,
                   (char *) pDevList, &DevListLen) == SOCKET_ERROR)
    {
       // WSAGetLastError 
    }if (pDevList->numDevice == 0)
    {
       // No devices discovered or cached.
       // Not a bad idea to run a couple of times.
    }
    else
    {
       // one per discovered device
       for (i = 0; i < (int) pDevList->numDevice; i++)
       {
          // typedef struct _IRDA_DEVICE_INFO
          // {
          //   u_char   irdaDeviceID[4];
          //   char   irdaDeviceName[22];
          //   u_char   irdaDeviceHints1;
          //    u_char   irdaDeviceHints2;
          //   u_char   irdaCharSet;
          // } _IRDA_DEVICE_INFO;      // pDevList->Device[i]. see _IRDA_DEVICE_INFO for fields
          // Display the device names and let the user select one.
       }
    }// Assume the user selected the first device [0].
    memcpy(&DestSockAddr.irdaDeviceID[0], &pDevList->Device[0].irdaDeviceID[0], 4);if (connect(Sock, (const struct sockaddr *) &DestSockAddr,
                sizeof(SOCKADDR_IRDA)) == SOCKET_ERROR)
    {
       // WSAGetLastError
    }It is also possible to run a lazy discovery—the application will not be notified until the discovered device list changes from the last discovery run by the stack.IAS
    Limited access to the IAS database is available through WinSock, but this is not normally used by applications. It exists to support connections to non–Windows devices that are not compliant with the WinSock/IrDA conventions.This code is used with the IRLMP_IAS_SET setsockopt() to manage the local IAS database:typedef struct _IAS_SET
    {
       char     irdaClassName[IAS_MAX_CLASSNAME];
       char     irdaAttribName[IAS_MAX_ATTRIBNAME];
       u_long   irdaAttribType;
       union
       {
          LONG irdaAttribInt;
          struct
          {
             u_short   Len;
             u_char   OctetSeq[IAS_MAX_OCTET_STRING];
          } irdaAttribOctetSeq;
          struct
          {
             u_char   Len;
             u_char   CharSet;
             u_char   UsrStr[IAS_MAX_USER_STRING];
          } irdaAttribUsrStr;
       } irdaAttribute;
    } IAS_SET, *PIAS_SET, FAR *LPIAS_SET;This code is used with the IRLMP_IAS_QUERY getsockopt() to query a peer's IAS database:typedef struct _WINDOWS_IAS_QUERY
    {
       u_char   irdaDeviceID[4];
       char   irdaClassName[IAS_MAX_CLASSNAME];
       char   irdaAttribName[IAS_MAX_ATTRIBNAME];
       u_long   irdaAttribType;
       union
       {
          LONG   irdaAttribInt;
          struct
          {
             u_long   Len;
             u_char   OctetSeq[IAS_MAX_OCTET_STRING];
          } irdaAttribOctetSeq;
          struct
          {
             u_long  Len;
             u_long   CharSet;
             u_char   UsrStr[IAS_MAX_USER_STRING];
          } irdaAttribUsrStr;
       } irdaAttribute;
    } IAS_QUERY, *PIAS_QUERY, FAR *LPIAS_QUERY;IrCOMM Server
    The following code shows the steps necessary to build a server that listens for incoming IrCOMM connections:#define IAS_SET_ATTRIB_MAX_LEN 32// buffer for IAS set
    BYTE          IASSetBuff[sizeof(IAS_SET) - 3 + IAS_SET_ATTRIB_MAX_LEN];
    Int           IASSetLen = sizeof(IASSetBuff);
    PIAS_SET      pIASSet   = (PIAS_SET) &IASSetBuff;// for the setsockopt call to enable 9 Wire IrCOMM
    int           Enable9WireMode  = 1;// server sockaddr with IrCOMM name
    SOCKADDR_IRDA ServSockAddr = { AF_IRDA, 0, 0, 0, 0, "IrDA:IrCOMM" };
    SOCKADDR_IRDA PeerSockAddr;
    int           sizeofSockAddr;SOCKET        ServSock;
    SOCKET        NewSock;if ((ServSock = socket(AF_IRDA, SOCK_STREAM, 0)) == INVALID_SOCKET)
    {
        // WSAGetLastError
    }
        
    // Add IrCOMM IAS attributes for 3 Wire cooked and 9 Wire raw, see IrCOMM spec.
    memcpy(&pIASSet->irdaClassName[0],  "IrDA:IrCOMM", 12);
    memcpy(&pIASSet->irdaAttribName[0], "Parameters",  11);
        
    pIASSet->irdaAttribType                       = IAS_ATTRIB_OCTETSEQ;
    pIASSet->irdaAttribute.irdaAttribOctetSeq.Len = 6;memcpy(&pIASSet->irdaAttribute.irdaAttribOctetSeq.OctetSeq[0],
           "\000\001\006\001\001\001", 6);if (setsockopt(ServSock, SOL_IRLMP, IRLMP_IAS_SET, (const char *) pIASSet, IASSetLen) 
        == SOCKET_ERROR)
    {
        // WSAGetLastError
    }// Enable 9 Wire mode before bind().
    if (setsockopt(ServSock, SOL_IRLMP, IRLMP_9WIRE_MODE, (const char *) &Enable9WireMode,
                   sizeof(int))  == SOCKET_ERROR)
    {
        // WSAGetLastError
    }if (bind(ServSock, (const struct sockaddr *) &ServSockAddr, sizeof(SOCKADDR_IRDA))
        == SOCKET_ERROR)
    {
        // WSAGetLastError
    }// Nothing special for IrCOMM from now on...
    if (listen(ServSock, SERV_BACKLOG) == SOCKET_ERROR)
    {
        // WSAGetLastError
    }IrCOMM Client
    The following code shows the steps necessary to build a client that connects through 9 Wire IrCOMM:#define DEVICE_LIST_LEN 5// discovery buffer
    BYTE          DevListBuff[sizeof(DEVICELIST) - sizeof(IRDA_DEVICE_INFO) + 
                              (sizeof(IRDA_DEVICE_INFO) * DEVICE_LIST_LEN)];
    int           DevListLen = sizeof(DevListBuff);
    PDEVICELIST   pDevList   = (PDEVICELIST) &DevListBuff;
    int           DevNum;#define IAS_QUERY_ATTRIB_MAX_LEN 32// buffer for IAS query
    BYTE          IASQueryBuff[sizeof(IAS_QUERY) - 3 + IAS_QUERY_ATTRIB_MAX_LEN];
    Int           IASQueryLen = sizeof(IASQueryBuff);
    PIAS_QUERY    pIASQuery   = (PIAS_QUERY) &IASQueryBuff;
        
    // for searching through peers IAS response
    BOOL          Found = FALSE;
    UCHAR        *pPI, *pPL, *pPV;
        
    // for the setsockopt call to enbale 9 Wire IrCOMM
    int           Enable9WireMode  = 1;SOCKADDR_IRDA DstAddrIR = { AF_IRDA, 0, 0, 0, 0, "IrDA:IrCOMM" };if ((pConn->Sock = socket(AF_IRDA, SOCK_STREAM, 0)) == INVALID_SOCKET)
    {
        // WSAGetLastError
    }// search for the peer device
    pDevList->numDevice = 0;
    if (getsockopt(pConn->Sock, SOL_IRLMP, IRLMP_ENUMDEVICES, (CHAR *) pDevList, &DevListLen)
        == SOCKET_ERROR)
    {
        // WSAGetLastError
    }// if (pDevList->numDevice == 0)
    {
        // No devices found, tell the user.
    }// Assume first device, we should have a common dialog here.
    memcpy(&DstAddrIR.irdaDeviceID[0], &pDevList->Device[0].irdaDeviceID[0], 4);// Query the peer to check for 9 Wire IrCOMM support.
    memcpy(&pIASQuery->irdaDeviceID[0], &pDevList->Device[0].irdaDeviceID[0], 4);// IrCOMM IAS attributes
    memcpy(&pIASQuery->irdaClassName[0],  "IrDA:IrCOMM", 12);
    memcpy(&pIASQuery->irdaAttribName[0], "Parameters",  11);if (getsockopt(pConn->Sock, SOL_IRLMP, IRLMP_IAS_QUERY,  (char *) pIASQuery, 
                   &IASQueryLen) == SOCKET_ERROR)
    {
        // WSAGetLastError
    }if (pIASQuery->irdaAttribType != IAS_ATTRIB_OCTETSEQ)
    {
        // Peer's IAS database entry for IrCOMM is bad.
        // error
    }if (pIASQuery->irdaAttribute.irdaAttribOctetSeq.Len < 3)
    {
        // Peer's IAS database entry for IrCOMM is bad.
        // error
    }// Search for the PI value 0x00 and check 9 Wire, see IrCOMM spec.
    pPI = pIASQuery->irdaAttribute.irdaAttribOctetSeq.OctetSeq;
    pPL = pPI + 1;
    pPV = pPI + 2;while (1)
    {
        if (*pPI == 0 && (*pPV & 0x04))
        {
            Found = TRUE;
            break;
        }
            
        if (pPL + *pPL >= pIASQuery->irdaAttribute.irdaAttribOctetSeq.OctetSeq + 
                          pIASQuery->irdaAttribute.irdaAttribOctetSeq.Len)
        {
            break;
        }
            
         pPI = pPL + *pPL;
         pPL = pPI + 1;
         pPV = pPI + 2;
    }if (! Found)
    {
        // Peer doesn't support 9 Wire mode.
        // error
    }// Enable 9 Wire mode before connect().
    if (setsockopt(ServSock, SOL_IRLMP, IRLMP_9WIRE_MODE, (const char *) &Enable9WireMode,
                   sizeof(int))  == SOCKET_ERROR)
    {
        // WSAGetLastError
    }// Nothing special for IrCOMM from now on...
    if (connect(pConn->Sock, (const struct sockaddr *) &DstAddrIR, sizeof(SOCKADDR_IRDA)) 
        == SOCKET_ERROR)
    {
        // WSAGetLastError
    }