?? cwsbook.txt
字號:
內容。經過仔細咀嚼和推敲后,更能得到一些編寫優質程序的靈感。
該程序在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 + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -