SOCKET.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:7k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /******************************************************************************
  2. *       This is a part of the Microsoft Source Code Samples.
  3. *       Copyright (C) 1992-1997 Microsoft Corporation.
  4. *       All rights reserved. 
  5. *       This source code is only intended as a supplement to 
  6. *       Microsoft Development Tools and/or WinHelp documentation.
  7. *       See these sources for detailed information regarding the 
  8. *       Microsoft samples programs.
  9. ******************************************************************************/
  10. //+---------------------------------------------------------------------------
  11. //
  12. //  File:       pop3svr.c
  13. //
  14. //  Contents:
  15. //
  16. //  Classes:
  17. //
  18. //  Functions:
  19. //
  20. //----------------------------------------------------------------------------
  21. #include "pop3srvp.h"
  22. #pragma hdrstop
  23. extern BOOL bServiceTerminating;
  24. extern SOCKET sListener;
  25. #define POP3_PORT 110
  26. PCHAR Welcome = "+OK Welcome to the NT Example POP3 Server (POP3SRV)rn";
  27. BOOL
  28. AcceptClients (
  29.     HANDLE hCompletionPort
  30.     )
  31. /*++
  32. Routine Description:
  33.     This routine sets up a listening socket on the POP3 port, then
  34.     loops accepting incoming connections from clients.  Whenever
  35.     it gets a connection, it sends the greeting message and starts
  36.     a read on the newly connected socket.
  37. Arguments:
  38.     hCompletionPort - the completion port that the POP3SRV worker 
  39.         threads are waiting on.  
  40. Return Value:
  41.     BOOL - FALSE if there was an error in starting the listening
  42.         socket.
  43. --*/
  44. {
  45.     SOCKET s;
  46.     SOCKADDR_IN sin;
  47.     int err;
  48.     BOOL bSuccess;
  49.     PCLIENT_CONTEXT lpClientContext;
  50.     DWORD dwBytesRead;
  51.     int zero;
  52.     //
  53.     // Create a listening socket that we'll use to accept incoming
  54.     // conections.
  55.     //
  56.     sListener = socket( AF_INET, SOCK_STREAM, 0 );
  57.     if ( sListener == INVALID_SOCKET ) {
  58.         return FALSE;
  59.     }
  60.     //
  61.     // Bind the socket to the POP3 well-known port.
  62.     //
  63.     sin.sin_family = AF_INET;
  64.     sin.sin_port = htons( POP3_PORT );
  65.     sin.sin_addr.s_addr = INADDR_ANY;
  66.     err = bind( sListener, (LPSOCKADDR)&sin, sizeof(sin) );
  67.     if ( err == SOCKET_ERROR ) {
  68.         closesocket( sListener );
  69.         return FALSE;
  70.     }
  71.     //
  72.     // Listen for incoming connections on the socket.
  73.     //
  74.     err = listen( sListener, 5 );
  75.     if ( err == SOCKET_ERROR ) {
  76.         closesocket( sListener );
  77.         return FALSE;
  78.     }
  79.     //
  80.     // Loop forever accepting connections from clients.
  81.     //
  82.     while ( TRUE ) {
  83.         s = accept( sListener, NULL, NULL );
  84.         if ( s == INVALID_SOCKET ) {
  85.             closesocket( sListener );
  86.             return FALSE;
  87.         }
  88.         //
  89.         // If the service if terminating, exit this thread.
  90.         //
  91.         if ( bServiceTerminating ) {
  92.             return FALSE;
  93.         }
  94.         //
  95.         // Allocate a socket context for the new connection.  We use
  96.         // this context structure to track socket-level information
  97.         // about the client.
  98.         //
  99.         lpClientContext = LocalAlloc( 0, sizeof(*lpClientContext) );
  100.         if ( lpClientContext == NULL ) {
  101.             closesocket( s );
  102.             continue;
  103.         }
  104.         //
  105.         // Initialize the context structure.
  106.         //
  107.         lpClientContext->Socket = s;
  108.         lpClientContext->Context = CreatePop3Context( );
  109.         lpClientContext->Overlapped.Internal = 0;
  110.         lpClientContext->Overlapped.InternalHigh = 0;
  111.         lpClientContext->Overlapped.Offset = 0;
  112.         lpClientContext->Overlapped.OffsetHigh = 0;
  113.         lpClientContext->Overlapped.hEvent = NULL;
  114.         //
  115.         // Send the welcome banner.
  116.         //
  117.         err = send( s, Welcome, strlen(Welcome), 0 );
  118.         if ( err == SOCKET_ERROR ) {
  119.             LocalFree( lpClientContext );
  120.             closesocket( s );
  121.             continue;
  122.         }
  123.         // --- DavidTr: Slide 14(a) ----------------------------------------
  124.         //
  125.         // Associate the new socket with a completion port.
  126.         //
  127.         hCompletionPort = CreateIoCompletionPort(
  128.                               (HANDLE)s,
  129.                               hCompletionPort,
  130.                               (DWORD)lpClientContext,
  131.                               0
  132.                               );
  133.         if ( hCompletionPort == NULL ) {
  134.             LocalFree( lpClientContext );
  135.             closesocket( s );
  136.             closesocket( sListener );
  137.             return FALSE;
  138.         }
  139.         // --- DavidTr: Slide 16 -------------------------------------------
  140.         //
  141.         // Disable send bufferring on the socket.  Setting SO_SNDBUF
  142.         // to 0 causes winsock to stop bufferring sends and perform
  143.         // sends directly from our buffers, thereby reducing CPU
  144.         // usage.
  145.         //
  146.         zero = 0;
  147.         err = setsockopt( s, SOL_SOCKET, SO_SNDBUF, (char *)&zero, sizeof(zero) );
  148.         if ( err == SOCKET_ERROR ) {
  149.             LocalFree( lpClientContext );
  150.             closesocket( s );
  151.             closesocket( sListener );
  152.             return FALSE;
  153.         }
  154.         //
  155.         // Start an overlapped read on the socket.  This read will
  156.         // complete in one of the worker threads, which will continue
  157.         // processing of the client.
  158.         //
  159.         lpClientContext->LastClientIo = ClientIoRead;
  160.         lpClientContext->BytesReadSoFar = 0;
  161.         bSuccess = ReadFile(
  162.                        (HANDLE)s,
  163.                        lpClientContext->Buffer,
  164.                        sizeof(lpClientContext->Buffer),
  165.                        &dwBytesRead,
  166.                        &lpClientContext->Overlapped
  167.                        );
  168.         if ( !bSuccess && GetLastError( ) != ERROR_IO_PENDING ) {
  169.             LocalFree( lpClientContext );
  170.             closesocket( s );
  171.             continue;
  172.         }
  173.     }
  174. } // AcceptClients
  175. VOID
  176. CloseClient (
  177.     PCLIENT_CONTEXT lpClientContext,
  178.     BOOL bGraceful
  179.     )
  180. /*++
  181. Routine Description:
  182.     Terminates a connection with a client and frees up resources.
  183. Arguments:
  184.     lpClientContext - a pointer to the context structure that contains
  185.         information about this client.
  186.     bGraceful - TRUE if the close should be graceful, FALSE otherwise.
  187. Return Value:
  188.     None.
  189. --*/
  190. {
  191.     LINGER lingerStruct;
  192.     //
  193.     // If we're supposed to abort the connection, set the linger value
  194.     // on the socket to 0.
  195.     //
  196.     if ( !bGraceful ) {
  197.         lingerStruct.l_onoff = 1;
  198.         lingerStruct.l_linger = 0;
  199.         setsockopt( lpClientContext->Socket, SOL_SOCKET, SO_LINGER,
  200.                     (char *)&lingerStruct, sizeof(lingerStruct) );
  201.     }
  202.     //
  203.     // Now close the socket handle.  This will do an abortive or 
  204.     // graceful close, as requested.  
  205.     //
  206.     closesocket( lpClientContext->Socket );
  207.     //
  208.     // Free context structuyres.
  209.     //
  210.     LocalFree( lpClientContext->Context );
  211.     LocalFree( lpClientContext );
  212.     return;
  213.     
  214. } // CloseClient