一个精巧的应用程序实例-wshout
一个精巧的应用程序实例-wshout
我们通过一个经过精心选择的例子,进一步讨论一下Windows Sockets编程技术。例如如何编制客户机或服务器程序,如何应用TCP有连接服务(流式套接口)或UDP无连接服务(数据报套接口),如何进行阻塞或非阻塞方式的套接口操作等等,这些都是经常碰到的问题。接下来要介绍的wshout程序,可以通过灵活地设置不同选项来达到上述应用情况的任意组合,从而基本覆盖了应用Windows Sockets编程所可能碰到的问题,具有很好的研究参考价值。
由于该程序思路清晰,结构精良,所以我们不打算很详细地剖析每一个语句,而只是简要介绍一下整个程序的逻辑结构,并在源程序中加入适当的注释。我们相信,任何具有基本C语言和Windows编程经验的读者,都能很轻松地读懂绝大部分内容。经过仔细咀嚼和推敲后,更能得到一些编写优质程序的灵感。
该程序在FTP公司的PCTCP支撑环境下调试通过,不过只要读者拥有任何符合Windows Sockets 1.1规范的实现,也能顺利执行该程序。
源程序目录
1. wshout.c wshout主程序
2. wshout.h wshout头文件
3. wshout.rc wshout资源文件
4. ushout.c UDP客户机程序
5. ulisten.c UDP服务器程序
6. tshout.c TCP客户机程序
7. tlisten.c TCP服务器程序
8. errno.c 获取WSAE*错误描述字符串程序
9. resolve.c 客户机/服务器启动程序
在编译本程序时,笔者用的是BC3.1,只需做一个PRJ工程文件,将上述.c文件及winsock.lib包括进来就行了。请注意winsock.h应在include目录或当前目录中,winsock.lib可利用winsock.dll通过implib工具来建立。如果读者使用其他的编译器,可自行作相应的调整,在此不再赘述。
1. wshout.c清单
CODE:
/*
* 文件名: 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 lParam)
{
我们通过一个经过精心选择的例子,进一步讨论一下Windows Sockets编程技术。例如如何编制客户机或服务器程序,如何应用TCP有连接服务(流式套接口)或UDP无连接服务(数据报套接口),如何进行阻塞或非阻塞方式的套接口操作等等,这些都是经常碰到的问题。接下来要介绍的wshout程序,可以通过灵活地设置不同选项来达到上述应用情况的任意组合,从而基本覆盖了应用Windows Sockets编程所可能碰到的问题,具有很好的研究参考价值。
由于该程序思路清晰,结构精良,所以我们不打算很详细地剖析每一个语句,而只是简要介绍一下整个程序的逻辑结构,并在源程序中加入适当的注释。我们相信,任何具有基本C语言和Windows编程经验的读者,都能很轻松地读懂绝大部分内容。经过仔细咀嚼和推敲后,更能得到一些编写优质程序的灵感。
该程序在FTP公司的PCTCP支撑环境下调试通过,不过只要读者拥有任何符合Windows Sockets 1.1规范的实现,也能顺利执行该程序。
源程序目录
1. wshout.c wshout主程序
2. wshout.h wshout头文件
3. wshout.rc wshout资源文件
4. ushout.c UDP客户机程序
5. ulisten.c UDP服务器程序
6. tshout.c TCP客户机程序
7. tlisten.c TCP服务器程序
8. errno.c 获取WSAE*错误描述字符串程序
9. resolve.c 客户机/服务器启动程序
在编译本程序时,笔者用的是BC3.1,只需做一个PRJ工程文件,将上述.c文件及winsock.lib包括进来就行了。请注意winsock.h应在include目录或当前目录中,winsock.lib可利用winsock.dll通过implib工具来建立。如果读者使用其他的编译器,可自行作相应的调整,在此不再赘述。
1. wshout.c清单
CODE:
/*
* 文件名: 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 lParam)
{
0
相关文章