cwsbook.txt

来自「介绍window下socket编程的一本好书」· 文本 代码 · 共 1,527 行 · 第 1/5 页

TXT
1,527
字号
内容。经过仔细咀嚼和推敲后,更能得到一些编写优质程序的灵感。
    该程序在FTP公司的PCTCP支撑环境下调试通过,不过只要读者拥有任何符
合Windows Sockets 1.1规范的实现,也能顺利执行该程序。


3.4.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工具来建立。如果读者使用其他的编译器,
可自行作相应的调整,在此不再赘述。

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 lParam)
{
    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 lParam)
{
    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 = MakeProcInstan

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?