发信人: richwxy(风吟) 
整理人: wenbobo(2002-05-17 17:59:41), 站内信件
 | 
 
 
3.4.2 程序逻辑结构 
 3.4.3 源程序清单及注释 
 3.4.3.1 wshout.c清单 
 /* 
  * 文件名: WSHOUT.C 
  */ 
 /* MSC Include files: */ 
 #include <stdio.h> 
 #include <io.h> 
 #include <string.h> 
 #include <stdlib.h> 
 #include <time.h> 
 #include "wshout.h" 
 #define MAJOR_VERSION   1 
 #define MINOR_VERSION   2 
 #define WSA_MAKEWORD(x,y)       ((y) * 256 + (x)) /* HI:Minor, LO:Major */ 
 HANDLE  hInst;                  /* 进程实例句柄 */ 
 HWND    hOurWnd;                /* 主窗口句柄 */ 
 HWND    hMainDlg;               /* 主对话框句柄 */ 
 int ret;                        /* 工作变量 */ 
 char    prbuf[PRBUF_LEN];       /* 用于显示文本的工作缓冲区 */ 
 SOCKET sd;                      /* 用于监听连接的套接口描述字 */ 
 long temporary_option   = 0L;   /* 缺省为阻塞模式 */ 
 long blocking_option    = 0L;   /* 阻塞模式的全局标识 */ 
 int run_cancelled       = 0;    /* 指示何时按下了取消按钮 */ 
 int len = 1024;                 /* 一次写的字节数 */ 
 BOOL    running = FALSE;        /* 程序的运行状态 */ 
 const int iTCP = 1;             /* 指定为TCP Shout */ 
 const int iUDP = 2;             /* 指定为UDP Shout */ 
 int iProto      = 1;            /* 缺省为TCP Shout */ 
 int iPortNo     = SOCK_SHOUT; 
 int temporary_protocol  = 1;    /* 在Settings()中使用 */ 
 int iShout  = 1; 
 int iListen = 2; 
 int iClientOrServer = 1;        /* 缺省为Shout(客户机)        */ 
 int tClientOrServer = 1;        /* 在Settings()中使用 */ 
 char HostModeBuf[20];/* 保存模式字符串 */ 
 WORD VersionReqd; 
 LPWSADATA lpmyWSAData; 
 int PASCAL 
 WinMain (HANDLE hInstance,HANDLE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) 
   
 { 
     HWND hWnd; 
     MSG msg; 
     BOOL InitApp(HANDLE); 
     if (!hPrevInstance) 
     if (!InitApp(hInstance)) 
             return (NULL); 
     hInst = hInstance; 
     hWnd = CreateWindow("MainMenu", 
         "Windows Shout", 
         WS_OVERLAPPEDWINDOW | WS_SYSMENU | WS_MINIMIZEBOX, 
         CW_USEDEFAULT, 
         CW_USEDEFAULT, 
         CW_USEDEFAULT, 
         CW_USEDEFAULT, 
         NULL, 
         NULL, 
         hInstance, 
         NULL); 
     if (!hWnd) 
         return (NULL); 
     hOurWnd = hWnd; 
     while (GetMessage(&msg, NULL, NULL, NULL)) { 
         TranslateMessage(&msg); /* 翻译虚拟键码 */ 
         DispatchMessage(&msg); 
     } 
     return (msg.wParam); 
 } 
 BOOL InitApp(HANDLE hInstance) 
 { 
     HANDLE hMemory; 
     PWNDCLASS pWndClass; 
     BOOL bSuccess; 
     hMemory = LocalAlloc(LPTR, sizeof(WNDCLASS)); 
     pWndClass = (PWNDCLASS) LocalLock(hMemory); 
     pWndClass->hCursor = LoadCursor(NULL, IDC_ARROW); 
     pWndClass->hIcon = LoadIcon(hInstance, (LPSTR) "SHOUT"); 
     pWndClass->lpszMenuName = (LPSTR) "MainMenu"; 
     pWndClass->lpszClassName = (LPSTR) "MainMenu"; 
     pWndClass->hbrBackground = GetStockObject(WHITE_BRUSH); 
     pWndClass->hInstance = hInstance; 
     pWndClass->style = NULL; 
     pWndClass->lpfnWndProc = ShoutWndProc; 
     bSuccess = RegisterClass(pWndClass); 
     LocalUnlock(hMemory); 
     LocalFree(hMemory); 
     return (bSuccess); 
 } 
 long FAR PASCAL ShoutWndProc(HWND hWnd, WORD message,WORD wParam, LONG lPara 
 m) 
 { 
     FARPROC lpDialogBoxProc; 
     switch (message){ 
         case WM_CREATE: 
   
             /* Put up the dialog box */ 
             lpDialogBoxProc = MakeProcInstance(DialogProc, hInst); 
             DialogBox (hInst, (LPSTR) "MainDialog", hWnd, lpDialogBoxProc) ; 
             FreeProcInstance(lpDialogBoxProc); 
             PostMessage(hWnd, WM_DESTROY, 0, 0L); 
             break; 
   
         case WM_DESTROY: 
             PostQuitMessage(0); 
             break; 
   
         default: 
             return(DefWindowProc(hWnd, message, wParam, lParam)); 
         } 
     return NULL; 
 } 
 BOOL FAR PASCAL DialogProc(HWND hOurDlg, WORD message, WORD wParam, LONG lPa 
 ram) 
 { 
     FARPROC lpProcAbout; 
     FARPROC lpProcSettings; 
     long lret; 
     WORD wMajorVersion, wMinorVersion; 
     char hostnm[64];            /* 包含主机名的工作缓冲区 */ 
     switch (message) { 
         case WM_INITDIALOG: 
             /* 选择缺省主机 */ 
             SetDlgItemText(hOurDlg, IDD_HNAME, ""); 
             SendDlgItemMessage(hOurDlg,         /* 对话框句柄 */ 
                 IDD_HNAME,                      /* 向何处发送msg */ 
                 EM_SETSEL,                      /* 选择字符 */ 
                 NULL,                           /* 附加信息 */ 
                 MAKELONG(0, 0x7fff));           /* 全部内容 */ 
             SetFocus(GetDlgItem(hOurDlg, IDD_HNAME)); 
   
             /* 初始化 */ 
             hMainDlg = hOurDlg;  /* 保存自己的窗口句柄 */ 
             SetDlgItemText(hOurDlg, IDD_COHOST,"Shout to:"); 
             wMajorVersion = MAJOR_VERSION; 
             wMinorVersion = MINOR_VERSION; 
             VersionReqd=WSA_MAKEWORD(wMajorVersion, wMinorVersion); 
             lpmyWSAData = (LPWSADATA)_calloc(1, sizeof(WSADATA)); 
   
             ret = WSAStartup(VersionReqd, lpmyWSAData); 
   
             if (ret != 0){ 
                 wshout_err (hOurDlg, WSAGetLastError(), "WSAStartup()"); 
             } 
   
             return (TRUE); 
         case WM_CLOSE: 
             PostMessage(hOurDlg, WM_COMMAND, IDM_EXIT, 0L); 
             break; 
   
         case WM_SYSCOMMAND: 
             SendMessage(hOurWnd, message, wParam, lParam); 
             break; 
   
         case WM_COMMAND: 
             switch (wParam) { 
             case IDD_CONNECT:           /* 按下连接按钮 */ 
             case IDM_START:             /* 选择了Start菜单项 */ 
                 run_cancelled = FALSE; 
                 /* 不能重入 */ 
                 if (running){ 
                     MessageBox(hOurWnd,"Shout is already running !", 
                         "Shout", MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION); 
                     return FALSE; 
                 } 
                 ClearBoxes(hOurDlg); 
                 running = TRUE; 
                 if (iClientOrServer == iShout) { 
                    /* 确保有主机名 */ 
                    if (GetDlgItemText (hOurDlg, IDD_HNAME, hostnm, 80) < 2) { 
                        MessageBeep(0); 
                        SetDlgItemText(hOurDlg, 
                                       IDD_COMMENT,"No hostname specified"); 
                        running = FALSE; 
                        break; 
                    } 
                    sd = ResolveAndConnectHost((char FAR *)hostnm,hOurDlg,iProto, 
                                               iPortNo); 
                    if (sd == SOCKET_ERROR) {/* 无法创建套接口 */ 
                        running = FALSE; 
                        break; 
                    } 
                 } 
                 else { 
                    sd = GetSocketAndBind(hOurDlg, iProto, iPortNo); 
                    if (sd == SOCKET_ERROR) { 
                     running = FALSE; 
                     break; 
                    } 
                 } 
   
                 /* Set the I/O mode of the socket */ 
                 if (blocking_option) { 
                     lret = 1L;  /* 非阻塞模式 */ 
                     ioctlsocket(sd, FIONBIO, (u_long FAR *) &lret); 
                 } 
                 else { 
                     lret = 0L; /* 阻塞模式 */ 
                     ioctlsocket(sd, FIONBIO, (u_long FAR *) &lret); 
                 } 
   
                 if (iClientOrServer == iShout) {  /* SHOUT */ 
                     /* 产生数据并写入套接口 */ 
                     if (iProto == iTCP) 
                         lret = TWriteData(sd, hOurDlg, len); 
                     else /* UDP */ 
                         lret = UWriteData(sd, hOurDlg, len); 
                 } 
                 else {  /* LISTEN */ 
                     if (iProto == iTCP) 
                         lret = TReadData(sd,hOurDlg, len); 
                     else /* UDP */ 
                         lret = UReadData(sd,hOurDlg, len); 
                 } 
   
                 closesocket(sd); 
                 running = FALSE; 
                 break; 
   
             case IDD_CANCEL: 
                 if (running) { 
                     /* 停止 */ 
                     ret = WSACancelBlockingCall(); 
                     run_cancelled = TRUE; 
                     if (ret == SOCKET_ERROR) { 
                         /* WSANOTINITIALISED or WSAENETDOWN or WSAEINVAL */ 
                         if (h_errno == WSAENETDOWN) { 
                             /* Watch out for hAcceptSock! */ 
                             /* close what is left of the connection */ 
                             closesocket(sd); 
                         } 
                     } 
                 } 
                 break; 
   
             case IDM_EXIT: 
                 ret = WSACleanup(); 
                 if (ret == SOCKET_ERROR && h_errno == WSAEINPROGRESS){ 
                     MessageBox(hOurWnd, 
                         "Data transfer in progress.\nStop transfer first.", 
                         "WndProc()", MB_OK | MB_APPLMODAL|MB_ICONINFORMATION); 
                     break; /* 一个套接口正处于阻塞状态 */ 
                 } 
   
                 _free((char NEAR *) lpmyWSAData); 
                 EndDialog(hOurDlg, TRUE) ; /* 退出 */ 
                 break; 
   
             case IDM_ABOUT: 
                 lpProcAbout = MakeProcInstance(About, hInst); 
                 DialogBox(hInst, "AboutBox", hOurDlg, lpProcAbout); 
                 FreeProcInstance(lpProcAbout); 
                 break; 
   
             case IDM_SETTINGS: 
                 lpProcSettings = MakeProcInstance(Settings, hInst); 
                 DialogBox(hInst, "SettingsDialog", hOurDlg, lpProcSettings); 
                 FreeProcInstance(lpProcSettings); 
                 break; 
   
             default: 
                 break; 
   
             } /* switch (wParam) */ 
             break; 
         } /* switch (message) */ 
     return FALSE; 
 } 
 /* 此函数处理About对话框 */ 
 BOOL FAR PASCAL About(HWND hDlg, WORD message, WORD wParam, LONG lParam) 
 { 
     char tempBuf[15]; 
     switch (message) { 
     case WM_INITDIALOG: 
         SetDlgItemText(hDlg, IDA_COPYRIGHT,(LPSTR)lpmyWSAData->szDescription); 
         wsprintf(tempBuf, "%d.%2d\n",MAJOR_VERSION, MINOR_VERSION); 
         SetDlgItemText(hDlg, IDA_APP_VERSION, (LPSTR) tempBuf); 
         wsprintf(tempBuf, "%d.%2d\n", 
                  lpmyWSAData->wVersion%256,lpmyWSAData->wVersion/256); 
         SetDlgItemText (hDlg, IDA_DLL_VERSION, (LPSTR) tempBuf); 
         return (FALSE); 
     case WM_COMMAND: 
         if (wParam == IDOK 
         || wParam == IDCANCEL) { 
         EndDialog(hDlg, TRUE); 
         return (TRUE); 
         } 
         break; 
     } 
     return (FALSE); 
 } 
 /* 此函数处理Settings 对话框 */ 
 BOOL FAR PASCAL Settings(HWND hDlg, WORD message, WORD wParam, LONG lParam) 
 { 
     int buffer_len = len; 
     int port_no    = iPortNo; 
     switch (message) { 
     case WM_INITDIALOG: 
         /* Select a default send() buffer length */ 
         SetDlgItemInt(hDlg, IDS_BUFFLEN, len, 0); 
         /* Select a default port number */ 
         SetDlgItemInt(hDlg, IDS_PORTNO, iPortNo, 0); 
         if (iClientOrServer == iShout)          /* 程序类型 */ 
             CheckThisProgBoxOn(hDlg, IDS_CLIENT); 
         else 
             CheckThisProgBoxOn(hDlg, IDS_SERVER); 
   
         if (iProto == iTCP)                     /* 协议类型 */ 
             CheckThisProtoBoxOn(hDlg, IDS_TCP); 
         else 
             CheckThisProtoBoxOn(hDlg, IDS_UDP); 
   
         if (!blocking_option)                   /* 阻塞模式 */ 
             CheckThisBoxOn(hDlg, IDS_BLOCK); 
         else 
             CheckThisBoxOn(hDlg, IDS_NOBLOCK); 
   
         SendDlgItemMessage(hDlg,                /* dialog handle        */ 
                 IDS_PORTNO,                     /* where to send msg    */ 
                 EM_SETSEL,                      /* select characters    */ 
                 NULL,                           /* additional info      */ 
                 MAKELONG(0, 0x7fff));           /* entire contents      */ 
   
         SendDlgItemMessage(hDlg,                /* dialog handle        */ 
                 IDS_BUFFLEN,                    /* where to send msg    */ 
                 EM_SETSEL,                      /* select characters    */ 
                 NULL,                           /* additional info      */ 
                 MAKELONG(0, 0x7fff));           /* entire contents      */ 
         SetFocus(GetDlgItem(hDlg, IDS_BUFFLEN)); 
         return (TRUE); 
     case WM_COMMAND: 
         switch (wParam){ 
         case IDS_CLIENT: 
             /* USer has set to Shout */ 
             CheckThisProgBoxOn(hDlg, IDS_CLIENT); 
             tClientOrServer = iShout; 
             SetDlgItemText(hMainDlg, IDD_COHOST,"Foreign host:"); 
             SetDlgItemText(hMainDlg, IDD_HNAME,""); 
             break; 
         case IDS_SERVER: 
             /* USer has set to Listen */ 
             CheckThisProgBoxOn(hDlg, IDS_SERVER); 
             tClientOrServer = iListen; 
             SetDlgItemText(hMainDlg, IDD_COHOST,"Listening to:"); 
             SetDlgItemText(hMainDlg, IDD_HNAME,"[Hit 'Start']"); 
             break; 
         case IDS_TCP: 
             /* USer has set to TCP */ 
             CheckThisProtoBoxOn(hDlg, IDS_TCP); 
             temporary_protocol = iTCP; 
             break; 
         case IDS_UDP: 
             /* USer has set to UDP */ 
             CheckThisProtoBoxOn(hDlg, IDS_UDP); 
             temporary_protocol = iUDP; 
             break; 
         case IDS_BLOCK: 
             /* User has set to blocking mode */ 
             CheckThisBoxOn(hDlg, IDS_BLOCK); 
             temporary_option = 0L; 
             break; 
         case IDS_NOBLOCK: 
             /* User has set to nonblocking mode */ 
             CheckThisBoxOn(hDlg, IDS_NOBLOCK); 
             temporary_option = 1L; 
             break; 
         case IDOK: 
             /* 用户已完成对设置的修改 */ 
             buffer_len = GetDlgItemInt(hDlg, IDS_BUFFLEN, NULL, 0); 
             if (buffer_len == 0 || buffer_len > 8192) { 
                 MessageBox(hOurWnd, "Buffer length must be between 1 and 8K", 
                            "Settings()", 
                            MB_OK | MB_APPLMODAL | MB_ICONSTOP); 
                 return (FALSE); 
             } 
   
             port_no = GetDlgItemInt(hDlg, IDS_PORTNO, NULL, 0); 
             if (port_no == 0) { 
                 MessageBox(hDlg, "Port number must be between 0 and 65,535", 
                            "Settings()", 
                            MB_OK | MB_APPLMODAL | MB_ICONSTOP); 
                 return (FALSE); 
             } 
             len     = buffer_len; 
             iPortNo = port_no; 
             blocking_option = temporary_option; 
             iProto          = temporary_protocol; 
             iClientOrServer = tClientOrServer; 
   
         case IDCANCEL: 
             /* 用户不想改变设置 */ 
             EndDialog(hDlg, TRUE); 
             return (TRUE); 
   
         default: 
             break; 
         } 
     default: 
         break; 
     } 
     return (FALSE); 
 } 
 void 
 CheckThisBoxOn(HWND hDlg, int ButtonID) 
 { 
     switch (ButtonID) { 
     case IDS_BLOCK: 
         CheckDlgButton(hDlg, IDS_BLOCK, 1); 
         CheckDlgButton(hDlg, IDS_NOBLOCK, 0); 
         break; 
     case IDS_NOBLOCK: 
         CheckDlgButton(hDlg, IDS_BLOCK, 0); 
         CheckDlgButton(hDlg, IDS_NOBLOCK, 1); 
         break; 
     default: 
         break; 
     } 
     return; 
 } 
 void 
 CheckThisProtoBoxOn(HWND hDlg, int ButtonID) 
 { 
     switch (ButtonID) { 
     case IDS_TCP: 
         CheckDlgButton(hDlg, IDS_TCP, 1); 
         CheckDlgButton(hDlg, IDS_UDP, 0); 
         break; 
     case IDS_UDP: 
         CheckDlgButton(hDlg, IDS_TCP, 0); 
         CheckDlgButton(hDlg, IDS_UDP, 1); 
         break; 
     default: 
         break; 
     } 
     return; 
 } 
 void 
 CheckThisProgBoxOn(HWND hDlg, int ButtonID) 
 { 
     switch (ButtonID) { 
     case IDS_CLIENT: /* Shout */ 
         CheckDlgButton(hDlg, IDS_CLIENT, 1); 
         CheckDlgButton(hDlg, IDS_SERVER, 0); 
         break; 
     case IDS_SERVER: /* Listen */ 
         CheckDlgButton(hDlg, IDS_CLIENT, 0); 
         CheckDlgButton(hDlg, IDS_SERVER, 1); 
         break; 
     default: 
         break; 
     } 
     return; 
 } 
 /* 以下就是我们如何处理"模拟阻塞"-本函数检查消息队列,如果发现需要处理的消息 
 ,就返回一个正的值。*/ 
 int 
 ShoutBlockingHook (void) 
 { 
   MSG msg;              /* lets us pull messages via PeekMessage */ 
   int ret = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); 
   if (ret) { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
   } 
   return ret; 
 } 
 char * 
 _calloc (nelem, elsize) 
  unsigned nelem, elsize; 
 { 
          HANDLE hMem; 
          PSTR ptr; 
          unsigned size = nelem * elsize; 
         if ((hMem = LocalAlloc(LPTR, size)) == NULL) 
                 return (char *) 0; 
         if ((ptr = LocalLock(hMem)) == NULL) { 
                 LocalFree(hMem); 
                 return (char *) 0; 
         } 
         return (char *) ptr; 
 } 
 void 
 _free (void *cP) 
 { 
         (void) LocalFree(LocalHandle((WORD) cP)); 
 } 
 void 
 ClearBoxes(HWND hOurDlg) 
 { 
     wsprintf(prbuf,"         \n"); 
     SetDlgItemText(hOurDlg, IDD_WRITE, (LPSTR) prbuf); 
     SetDlgItemText(hOurDlg, IDD_SENT, (LPSTR) prbuf); 
     SetDlgItemText(hOurDlg, IDD_TIME, (LPSTR) prbuf); 
     SetDlgItemText(hOurDlg, IDD_WRITES,(LPSTR) prbuf); 
     SetDlgItemText(hOurDlg, IDD_BYTES, (LPSTR) prbuf); 
     SetDlgItemText(hOurDlg, IDD_BITS,  (LPSTR) prbuf); 
     return; 
 } 
 /* 
  * wshout_err()函数 
  * 描述: 
  * 
  * 通过错误代码获取相应的错误描述文本,与用户提供的错误前缀合 
 
  * 并,并显示在对话框中。 
  */ 
 void wshout_err (HWND hOurDlg, /* 对话框的窗口句柄 */ 
                  int wsa_err,           /* WinSock错误代码 */ 
                  char far *err_prefix)  /* 错误前缀字符串 */ 
 { 
         char errbuf[PRBUF_LEN];  /* 错误描述字符串缓冲区 */ 
         /* 获取错误描述字符串 */ 
         WSAsperror(hInst, wsa_err, (LPSTR)errbuf, PRBUF_LEN); 
   
         /* 合并错误描述字符串与用户错误前缀字符串 */ 
         wsprintf((LPSTR)prbuf, "%s:%s", (LPSTR) err_prefix, (LPSTR)errbuf); 
         /* 在对话框中显示错误文本 */ 
         SetDlgItemText(hOurDlg, IDD_COMMENT, (LPSTR) prbuf); 
   
 } 
   
 -- 
  | 
 
 
 |