精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>C/C++>>网络与通讯>>WINSOCK编程

主题:WINSOCK编程
发信人: 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); 
  

  
-- 

[关闭][返回]