home *** CD-ROM | disk | FTP | other *** search
/ Shareware Supreme Volume 6 #1 / swsii.zip / swsii / 215 / DDJ9302.ZIP / SOCKETS.ASC < prev    next >
Text File  |  1993-01-11  |  14KB  |  544 lines

  1. _UNTANGLING THE WINDOWS SOCKETS API_
  2. by Mike Calbaum, Frank Porcaro, Mark Ruegsegger, and Bruce Backman
  3.  
  4.  
  5.  
  6. [LISTING ONE]
  7.  
  8. /*
  9.  * Sock.c -- Windows sockets sample application
  10.  *
  11.  * Implements psuedo finger client and server.
  12.  * Should work with any UNIX finger daemon
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. #include "windows.h"
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <ctype.h>
  22. #include <winsock.h>
  23. #include "dlg.h"
  24.  
  25.  
  26. #define PROMPT_STRING       130
  27. #define PROMPT_TEXT         131
  28.  
  29. #define CONN_MSG        (WM_USER+25)
  30. #define    FNGR_READ        (WM_USER+26)
  31.  
  32. extern void errormsg(LPSTR cp);
  33. extern int PASCAL WinMain(HANDLE, HANDLE, LPSTR, int);
  34. extern BOOL InitApplication(HANDLE);
  35. extern BOOL InitInstance(HANDLE, int);
  36. extern long FAR PASCAL MainWndProc(HWND, unsigned, WORD, LONG);
  37. extern BOOL FAR PASCAL About(HWND, unsigned, WORD, LONG);
  38. extern long FAR PASCAL SockWndProc(HWND hWnd, unsigned message, WORD wParam, LONG lParam);
  39. extern char *prompt(HWND hWnd, HANDLE hInst, char *message, char *buf);
  40.  
  41.  
  42. /*  Global buffers  */
  43. char buff[4096];
  44. char msg[80], name[125];
  45.  
  46. HANDLE hInst;
  47. HWND hWnd;
  48. struct sockaddr_in anaddr;
  49. int whoport, fngrport;        /*  Well known port numbers  */
  50. int app_closing;
  51.  
  52. /*  Sockets  */
  53. SOCKET fclient = INVALID_SOCKET;
  54. SOCKET fserver = INVALID_SOCKET;
  55. SOCKET fconnect = INVALID_SOCKET;
  56.  
  57.  
  58. /*
  59.  * standard windows initialization routines
  60.  */
  61. BOOL InitApplication(HANDLE hInstance)
  62.     {
  63.     WNDCLASS  wc;
  64.  
  65.        buff[0] = '\0';
  66.  
  67.     wc.style = NULL;
  68.     wc.lpfnWndProc = SockWndProc;
  69.  
  70.     wc.cbClsExtra = 0;
  71.     wc.cbWndExtra = 0;
  72.     wc.hInstance = hInstance;
  73.     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  74.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  75.     wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  76.     wc.lpszMenuName =  "SockMenu";
  77.     wc.lpszClassName = "SockWClass";
  78.  
  79.     return(RegisterClass(&wc));
  80.     }
  81.  
  82. BOOL InitInstance(HANDLE hInstance, int nCmdShow)
  83.     {
  84.  
  85.     hInst = hInstance;
  86.  
  87.     /* Create a main window for this application instance.  */
  88.  
  89.     hWnd = CreateWindow("SockWClass", "Sockets Sample Application",
  90.                             WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
  91.                             CW_USEDEFAULT, CW_USEDEFAULT,
  92.                             CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
  93.  
  94.     if (!hWnd)
  95.         return (FALSE);
  96.  
  97.     ShowWindow(hWnd, nCmdShow);
  98.     UpdateWindow(hWnd);
  99.     return (TRUE);
  100.     }
  101.  
  102.  
  103. int PASCAL
  104. WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  105.     {
  106.     MSG msg;
  107.     FARPROC lpfn;
  108.     WSADATA wskData;
  109.  
  110.     if (!hPrevInstance)
  111.         if (!InitApplication(hInstance))
  112.             return(FALSE);
  113.  
  114.     if (!InitInstance(hInstance, nCmdShow))
  115.         return(FALSE);
  116.  
  117.     /*
  118.      * register application with windows sockets dll
  119.      */
  120.  
  121.     if(!WSAStartup(1, &wskData) && (wskData.wVersion == 1))
  122.         {
  123.  
  124.         while (GetMessage(&msg, NULL, NULL, NULL))
  125.             {
  126.             TranslateMessage(&msg);
  127.             DispatchMessage(&msg);
  128.             if (app_closing)
  129.                 {
  130.                 /* The application has been requested to shut down. Continue processing
  131.                 * the close request by calling DestroyWindow  */
  132.                 DestroyWindow(hWnd);
  133.                 }
  134.             }
  135.  
  136.         /* Close any open sockets */
  137.         if(fclient != INVALID_SOCKET)
  138.             closesocket(fclient);
  139.         if(fserver != INVALID_SOCKET)
  140.             closesocket(fserver);
  141.         if(fconnect != INVALID_SOCKET)
  142.             closesocket(fconnect);
  143.  
  144.         /*  Let windows sockets know we're done */
  145.         WSACleanup();
  146.         return(msg.wParam);
  147.         }
  148.  
  149.     return(0);
  150.     }
  151.  
  152.  
  153. BOOL FAR PASCAL About(HWND hDlg, unsigned message, WORD wParam, LONG lParam)
  154.     {
  155.     switch (message)
  156.         {
  157.             case WM_INITDIALOG:
  158.                 return (TRUE);
  159.  
  160.             case WM_COMMAND:
  161.                 if (wParam == IDOK || wParam == IDCANCEL)
  162.                     {
  163.                     EndDialog(hDlg, TRUE);
  164.                     return (TRUE);
  165.                     }
  166.                 break;
  167.         }
  168.     return (FALSE);
  169.     }
  170.  
  171.  
  172. long FAR PASCAL
  173. SockWndProc(HWND hWnd, unsigned message, WORD wParam, LONG lParam)
  174.     {
  175.     int len, cnt;
  176.     RECT wRect;
  177.     PAINTSTRUCT ps;
  178.     HDC hdc;
  179.     struct hostent FAR *hp;
  180.     static HANDLE arrow, hrGlass, hMenu;
  181.  
  182.     switch (message)
  183.         {
  184.         case WM_CREATE:
  185.             hMenu = GetMenu(hWnd);
  186.             arrow = LoadCursor(NULL, IDC_ARROW);
  187.             hrGlass = LoadCursor(NULL, IDC_WAIT);
  188.             SetCursor(arrow);
  189.             break;
  190.  
  191.         /*
  192.          * If user presses control-c, interpret as an interrupt request.
  193.          * Could also provide a menu item or a dialogbox with a "cancel"
  194.          * button.
  195.          *
  196.          */
  197.         case WM_CHAR:
  198.             if (wParam == 3/* ctrl-c */)
  199.                 {
  200.                 WSACancelBlockingCall();
  201.                 strcpy(buff, "Call cancelled!!");
  202.                 InvalidateRect(hWnd, NULL, 1);
  203.                 }
  204.             else
  205.                 return(DefWindowProc(hWnd, message, wParam, lParam));
  206.             break;
  207.  
  208.         /* Update the window */
  209.         case WM_PAINT:
  210.             hdc = BeginPaint(hWnd, &ps);
  211.  
  212.             /* Use fixed fontand expand tabs so tabs align */
  213.             SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
  214.             GetClientRect(hWnd, &wRect);
  215.             DrawText(hdc, buff, -1, &wRect, DT_LEFT | DT_EXPANDTABS);
  216.             EndPaint(hWnd, &ps);
  217.             break;
  218.  
  219.         /* Menu item selected, wParam == menu item ID  */
  220.         case WM_COMMAND:
  221.             switch (wParam)
  222.                 {
  223.                 /* Display About Box */
  224.                 case IDM_ABOUT:
  225.                     {
  226.                     FARPROC lpfn;
  227.  
  228.                     lpfn = MakeProcInstance(About, hInst);
  229.                     DialogBox(hInst, "AboutBox", hWnd, lpfn);
  230.                     FreeProcInstance(lpfn);
  231.                     break;
  232.                     }
  233.  
  234.                 /* Finger client utility */
  235.                 case FINGER:
  236.                     /*  Get user name  */
  237.                     if(prompt(hWnd, hInst, "Hostname:", msg) == NULL)
  238.                         break;
  239.  
  240.                     /*  Look up the host address  */
  241.                     if((hp = gethostbyname(msg)) == NULL)
  242.                         {
  243.                         errormsg("Unknown host");
  244.                         break;
  245.                         }
  246.                     _fmemcpy((char FAR *) &anaddr.sin_addr.s_addr, hp->h_addr, hp->h_length);
  247.  
  248.                     /*  Get username to finger */
  249.                     if(!prompt(hWnd, hInst, "Finger User:", msg))
  250.                         strcpy(msg, "");
  251.  
  252.                     /*  Look up port number */
  253.                     if(fngrport == 0)
  254.                         {
  255.                         struct servent FAR *sp;
  256.  
  257.                         if((sp = getservbyname("finger", "tcp")) == NULL)
  258.                             {
  259.                             errormsg("Cannot determine port number for finger daemon.");
  260.                             break;
  261.                             }
  262.                         fngrport = htons(sp->s_port);
  263.                         }
  264.  
  265.                     /* create socket */
  266.                     if((fclient = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
  267.                         {
  268.                         errormsg("Unable to create a socket");
  269.                         }
  270.                     else
  271.                         {
  272.                         /*  Fill in address to which we will connect */
  273.                         anaddr.sin_family = PF_INET;
  274.                         anaddr.sin_port = htons(fngrport);
  275.  
  276.                         /*  try to connect */
  277.                         if(connect(fclient, (struct sockaddr FAR *) &anaddr, sizeof(struct sockaddr_in)))
  278.                             {
  279.                             errormsg("Unable to connect to finger daemon.");
  280.                             closesocket(fclient);
  281.                             fclient = INVALID_SOCKET;
  282.                             }
  283.                         else
  284.                             {
  285.                             strcat(msg, "\r\n");
  286.                             if(send(fclient, msg, strlen(msg), 0) < (int) strlen(msg))
  287.                                 {
  288.                                 errormsg("Error sending string to finger daemon");
  289.                                 }
  290.                             else
  291.                                 if((cnt = recv(fclient, buff, sizeof(buff), 0)) == SOCKET_ERROR)
  292.                                     {
  293.                                     errormsg("Error reading data from daemon");
  294.                                     }
  295.                                 else
  296.                                     if(cnt == 0)
  297.                                         errormsg("No data received from finger daemon");
  298.                                     else
  299.                                         {
  300.                                         buff[cnt] = '\0';
  301.                                         InvalidateRect(hWnd, NULL, 1);
  302.                                         }
  303.                             }
  304.                         closesocket(fclient);
  305.                         fclient = INVALID_SOCKET;
  306.                         }
  307.                     break;
  308.  
  309.                 case FINGER_SRV:
  310.                     /*  Look up port number */
  311.                     if(fngrport == 0)
  312.                         {
  313.                         struct servent FAR *sp;
  314.  
  315.                         if((sp = getservbyname("finger", "tcp")) == NULL)
  316.                             {
  317.                             errormsg("Cannot determine port number for finger daemon.");
  318.                             break;
  319.                             }
  320.                         fngrport = htons(sp->s_port);
  321.                         }
  322.  
  323.                     /* if not acting as server, start */
  324.                     if(fserver == INVALID_SOCKET)
  325.                         {
  326.                         /*  Get user name  */
  327.                         if(prompt(hWnd, hInst, "Real Name:", msg) == NULL)
  328.                             break;
  329.                         else
  330.                             wsprintf(name, "In Real Life: %s\r\n", (LPSTR) msg);
  331.  
  332.                         /*  allocate socket  */
  333.                         if((fserver = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
  334.                             {
  335.                             errormsg("Cannot allocate socket for finger server");
  336.                             break;
  337.                             }
  338.  
  339.                         /* Bind our socket to the finger port number */
  340.                         anaddr.sin_port = htons(fngrport);
  341.                         anaddr.sin_addr.s_addr = INADDR_ANY;
  342.                         anaddr.sin_family = PF_INET;
  343.                         if(bind(fserver, (struct sockaddr FAR *) &anaddr, sizeof(anaddr)))
  344.                             {
  345.                             errormsg("Error binding to finger daemon port");
  346.                             closesocket(fserver);
  347.                             fserver = INVALID_SOCKET;
  348.                             break;
  349.                             }
  350.  
  351.                         /*  listen for connections and ask for a message when they come in */
  352.                         if(listen(fserver, 5) || WSAAsyncSelect(fserver, hWnd, CONN_MSG, FD_ACCEPT))
  353.                             {
  354.                             errormsg("Error trying to listen on finger server socket");
  355.                             closesocket(fserver);
  356.                             fserver = INVALID_SOCKET;
  357.                             }
  358.                         else
  359.                             CheckMenuItem(hMenu, FINGER_SRV, MF_BYCOMMAND | MF_CHECKED);
  360.                         }
  361.                     else     /*  Already acting as server, stop  */
  362.                         {
  363.                         closesocket(fserver);
  364.                         fserver = INVALID_SOCKET;
  365.                         CheckMenuItem(hMenu, FINGER_SRV, MF_BYCOMMAND | MF_UNCHECKED);
  366.                         }
  367.                     break;
  368.  
  369.                 case CANCEL:    /* Cancel any outstanding blocking call (send or recv) */
  370.                     WSACancelBlockingCall();
  371.                     strcpy(buff, "Call cancelled!!");
  372.                     InvalidateRect(hWnd, NULL, 1);
  373.                     break;
  374.  
  375.                 case QUIT:
  376.                     SendMessage(hWnd, WM_CLOSE, 0, 0L);
  377.                     break;
  378.  
  379.                 default:
  380.                     return (DefWindowProc(hWnd, message, wParam, lParam));
  381.                 }
  382.         break;
  383.  
  384.         case CONN_MSG:        /* Connection on finger server  */
  385.             if(WSAGETSELECTERROR(lParam))
  386.                 errormsg("Error listening for finger connections");
  387.             else
  388.                 {
  389.                 /* accept connection */
  390.                 len = sizeof(struct sockaddr_in);
  391.                 fconnect = accept(fserver, (struct sockaddr FAR *) &anaddr, &len);
  392.                 if(fconnect == INVALID_SOCKET)
  393.                     errormsg("Error accepting connection to finger server");
  394.                 else
  395.                     WSAAsyncSelect(fconnect, hWnd, FNGR_READ, FD_READ);
  396.                 }
  397.             break;
  398.  
  399.          case FNGR_READ:    /*  Data available for reading  */
  400.             {
  401.             /* The finger client will send us a string but we will ignore it */
  402.             cnt = recv(fconnect, buff, sizeof(buff), 0);
  403.             buff[0] = '\0';
  404.             if(cnt == SOCKET_ERROR)
  405.                 errormsg("Error reading from finger client");
  406.             else
  407.                 if(send(fconnect, name, strlen(name), 0) < (int) strlen(name))
  408.                     errormsg("Error sending data to finger client");
  409.  
  410.             /* Close up the accepted connection */
  411.             closesocket(fconnect);
  412.             fconnect = INVALID_SOCKET;
  413.             }
  414.             break;
  415.  
  416.         case WM_CLOSE:
  417.             /* Application's main window is closing. Set flag to notify main loop
  418.              * The main function is responsible for handling the close
  419.              */
  420.             app_closing = 1;
  421.             break;
  422.  
  423.         case WM_DESTROY:
  424.             PostQuitMessage(0);
  425.             break;
  426.  
  427.         default:
  428.             return (DefWindowProc(hWnd, message, wParam, lParam));
  429.         }
  430.     return (NULL);
  431.     }
  432.  
  433.  
  434.  
  435. char PromptText[41];       /* prompt message text for prompt dlg */
  436. char PromptString[81];     /* user's input from prompt dlg */
  437.  
  438. /*
  439.  * PromptDlgProc - Processes the "prompt" dialog box
  440.  *
  441.  * globals:  PromptText - prompt message text
  442.  *           PromptString - user's input
  443.  * return: IDOK or IDCANCEL
  444.  */
  445. BOOL FAR PASCAL
  446. PromptDlgProc(HWND hDlg, unsigned message, WORD wParam, LONG lParam)
  447.     {
  448.     switch (message)
  449.         {
  450.         case WM_COMMAND:
  451.             if (wParam == IDOK)
  452.                 {
  453.                 GetDlgItemText(hDlg, PROMPT_STRING, PromptString, 80);
  454.                 EndDialog(hDlg, IDOK);
  455.                 return TRUE;
  456.                 }
  457.             else if (wParam == IDCANCEL)
  458.                 {
  459.                 EndDialog(hDlg, IDCANCEL);
  460.                 return TRUE;
  461.                 }
  462.                 return FALSE;
  463.             break;
  464.  
  465.         case WM_INITDIALOG:
  466.             SetDlgItemText(hDlg, PROMPT_TEXT, PromptText);
  467.             return(TRUE);
  468.             break;
  469.  
  470.         default:
  471.             return FALSE;
  472.         }
  473.     }
  474.  
  475. /*
  476.  * prompt - displays message, copies user response into buf
  477.  *
  478.  * return: NULL for cancel, or FAR *  to buf
  479.  */
  480. char *prompt(HWND hWnd, HANDLE hInst, char *message, char *buf)
  481.     {
  482.     int rc;
  483.     FARPROC   lpDlgProc;
  484.  
  485.     lstrcpy(PromptText, message);
  486.  
  487.     lpDlgProc = MakeProcInstance(PromptDlgProc, hInst);
  488.     rc = DialogBox(hInst, "PROMPT", hWnd, lpDlgProc);
  489.     FreeProcInstance(lpDlgProc);
  490.  
  491.     if (rc == IDOK)
  492.         lstrcpy(buf, PromptString);
  493.     else
  494.         buf = NULL;
  495.     return buf;
  496.     }
  497.  
  498. /*
  499.  * errormsg - displays an error message and the last error
  500.  *
  501.  */
  502. void errormsg(LPSTR cp)
  503. {
  504.     char buf[128];
  505.  
  506.     wsprintf(buf, "%s (%d)", (LPSTR)cp, WSAGetLastError());
  507.     MessageBox(hWnd, buf, NULL, MB_ICONHAND);
  508. }
  509.  
  510.  
  511. [LISTING TWO]
  512.  
  513. #define FINGER         112
  514. #define FINGER_SRV         113
  515. #define CANCEL         114
  516. #define IDM_ABOUT       115
  517. #define QUIT           116
  518.  
  519. #define PROMPT_STRING   130
  520. #define PROMPT_TEXT     131
  521.  
  522.  
  523.  
  524. [LISTING THREE]
  525.  
  526. #include "windows.h"
  527. #include "dlg.h"
  528. #include "sock.dlg"
  529.  
  530. SockMenu MENU
  531. BEGIN
  532.     POPUP        "&Sockets"
  533.     BEGIN
  534.     MENUITEM "Finger &Client",      FINGER
  535.     MENUITEM "&Finger Server...",   FINGER_SRV
  536.     MENUITEM "&Cancel Operation",   CANCEL
  537.     MENUITEM "A&bout...",              IDM_ABOUT
  538.     MENUITEM "&Quit",        QUIT
  539.     END
  540. END
  541.  
  542.  
  543.  
  544.