国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

使用WINSOCK 實(shí)現(xiàn)Windows下網(wǎng)絡(luò)通信

2013-04-29 00:53:31肖季烈肖維
知識(shí)窗·教師版 2013年9期

肖季烈 肖維

摘要:本文介紹了Sockets通信原理,從程序員的角度著重討論了Windows Sockets的功能擴(kuò)充,并列舉了運(yùn)用 Windows Sockets實(shí)現(xiàn)網(wǎng)絡(luò)實(shí)時(shí)通信的一個(gè)程序?qū)嵗?/p>

關(guān)鍵詞:Windows Sockets 異步通信 阻塞

一、Socket網(wǎng)絡(luò)編程原理

Socket是BSD UNIX提供的網(wǎng)絡(luò)應(yīng)用編程接口,它采用客戶——服務(wù)器的通訊機(jī)制,使網(wǎng)絡(luò)客戶方和服務(wù)器方通過Socket實(shí)現(xiàn)網(wǎng)絡(luò)之間的連接和數(shù)據(jù)交換。Socket提供了一系列的系統(tǒng)調(diào)用,可以實(shí)現(xiàn)TCP、UDP、ICMP和IP等多種網(wǎng)絡(luò)協(xié)議之間的通訊。

Socket有三種主要類型:Stream sockets、Datagram sockets 和Raw sockets。Stream socket接口定義了一種可靠的面向連接的服務(wù),實(shí)現(xiàn)了無差錯(cuò)、無重復(fù)的順序數(shù)據(jù)傳輸,它通過內(nèi)置的流量控制解決了數(shù)據(jù)的擁堵,應(yīng)用程序可以發(fā)送任意長(zhǎng)度的數(shù)據(jù);Datagram socket接口定義了一種無連接的服務(wù),數(shù)據(jù)通過相互獨(dú)立的包進(jìn)行傳輸,包的傳輸是無序的,但是不能保證包的正確率。包長(zhǎng)度是有限的(隱含長(zhǎng)度為8,192字節(jié),最大長(zhǎng)度可設(shè)為32,768字節(jié));Raw socket接口允許對(duì)低層協(xié)議(如IP和ICMP)的直接存取,它主要用于實(shí)現(xiàn)新網(wǎng)絡(luò)協(xié)議的測(cè)試等。

下面,我們通過一個(gè)面向連接的傳輸發(fā)生的典型情況來說明Socket網(wǎng)絡(luò)通信的實(shí)現(xiàn)。

從圖1中我們可以看出,客戶和服務(wù)器的關(guān)系不是對(duì)稱的,服務(wù)器首先啟動(dòng),然后在某一時(shí)間 從

從圖1中我們可以看出,客戶與服務(wù)器的關(guān)系不是對(duì)稱的,服務(wù)器首先啟動(dòng),然后在某一時(shí)間啟動(dòng)客戶與服務(wù)器的連接。服務(wù)器和客戶開始都必須用調(diào)用socket()建立一個(gè)套接字(socket),然后服務(wù)器調(diào)用bind()將套接字與一個(gè)本地網(wǎng)絡(luò)地址捆綁在一起,再用調(diào)用listen()使套接字處于一種被動(dòng)的準(zhǔn)備接收狀態(tài),同時(shí)規(guī)定它的請(qǐng)求隊(duì)列長(zhǎng)度,之后服務(wù)器就可以調(diào)用accept()來接收連接了??蛻粼诮⑻捉幼种螅涂梢酝ㄟ^調(diào)用connect()和服務(wù)器建立連接。建立連接后,客戶和服務(wù)器之間就可以通過連接發(fā)送和接收數(shù)據(jù)(調(diào)用read()和write())。最后,待數(shù)據(jù)傳送結(jié)束,雙方調(diào)用close()關(guān)閉套接字。

二、WINSOCK對(duì)Socket的擴(kuò)充

BSD Socket支持阻塞(blocking)和非阻塞(non_blocking)兩種工作方式。在阻塞方式下工作,connect()、accept()、read()和recv()等調(diào)用在執(zhí)行時(shí)都處于阻塞狀態(tài),直到它成功或出錯(cuò)返回;在非阻塞方式下工作,這些調(diào)用是立即返回的,但是必須通過查詢才能知道它們是否完成。

WINSOCK對(duì)BSD Socket的擴(kuò)充主要基于消息、對(duì)網(wǎng)絡(luò)事件的異步存取接口上。表1列出了WINSOCK擴(kuò)充的函數(shù)功能。

從表1中我們可以看出,WINSOCK的擴(kuò)充功能可以分為如下幾類:

1.異步選擇機(jī)制

異步選擇函數(shù)WSAAsyncSelect()允許應(yīng)用程序提名一個(gè)或多個(gè)感興趣的網(wǎng)絡(luò)事件,所有非阻塞的網(wǎng)絡(luò)I/O例程(如send()和resv()),不管它是已經(jīng)使用,還是即將使用,都可作為WSAAsyncSelect()函數(shù)選擇的候選。當(dāng)被提名的網(wǎng)絡(luò)事件發(fā)生時(shí),Windows應(yīng)用程序的窗口函數(shù)將收到一個(gè)消息,消息附帶的參數(shù)指示被提名過的某一網(wǎng)絡(luò)事件。

2.異步請(qǐng)求例程

異步請(qǐng)求例程允許應(yīng)用程序用異步方式獲取請(qǐng)求的信息,如WSAAsyncGetXByY()類函數(shù)允許用戶請(qǐng)求異步服務(wù),這些功能在使用標(biāo)準(zhǔn)Berkeley函數(shù)時(shí)是阻塞的。

3.阻塞處理方法

WINSOCK在調(diào)用處于阻塞時(shí)會(huì)進(jìn)入一個(gè)叫“Hook”的例程,它負(fù)責(zé)處理Windows消息,使得Windows的消息循環(huán)能夠繼續(xù)。WINSOCK還提供了兩個(gè)函數(shù)[WSASetBlockingHook()和WSAUnhookBlockingHook()]讓用戶能夠設(shè)置和取消自己的阻塞處理例程。另外,函數(shù)WSAIsBlocking()可以檢測(cè)調(diào)用是否阻塞,函數(shù)WSACancelBlockingCall()可以取消一個(gè)阻塞的調(diào)用。

4.出錯(cuò)處理

為了和以后的多線索環(huán)境(如Windows/NT)兼容,WINSOCK提供了兩個(gè)出錯(cuò)處理函數(shù)WSAGetLastError()和WSASetLastError()來獲取和設(shè)置本線索的最近錯(cuò)誤號(hào)。

5.啟動(dòng)與終止

WINSOCK的應(yīng)用程序在使用上述WINSOCK函數(shù)前,必須先調(diào)用WSAStartup()函數(shù)對(duì)Windows Sockets DLL進(jìn)行初始化,以協(xié)商WINSOCK的版本支持,并分配必要的資源。在應(yīng)用程序退出之前,應(yīng)該先調(diào)用函數(shù)WSAClearnup()終止對(duì)Windows Sockets DLL的使用,并釋放資源,將有利于下一次使用。

三、網(wǎng)絡(luò)實(shí)時(shí)通信的實(shí)現(xiàn)

我們來設(shè)計(jì)一個(gè)簡(jiǎn)單的基于連接的點(diǎn)對(duì)點(diǎn)網(wǎng)絡(luò)實(shí)時(shí)通信程序:服務(wù)器首先啟動(dòng),它建立套接字之后等待客戶的連接;客戶在啟動(dòng)后建立套接字,然后和服務(wù)器建立連接;連接建立后,客戶通過連接給服務(wù)器發(fā)送一段數(shù)據(jù),服務(wù)器接收后又將它發(fā)送回來,客戶再發(fā)送,如此循環(huán),直至用戶命令客戶退出或網(wǎng)絡(luò)出錯(cuò);客戶關(guān)閉連接和套接字后退出,服務(wù)器在檢測(cè)到連接關(guān)閉后,關(guān)閉套接字自動(dòng)結(jié)束。

我們的實(shí)例是UNIX下基于BSD Socket的服務(wù)器程序和Windows下基于WINSOCK的客戶程序之間的通信。我們先來看客戶程序,首先定義幾個(gè)宏、菜單資源和部分全局變量:

程序1:部分Windows程序源代碼(宏、菜單和變量)

#define USERPORT3333/* 用戶定義端口號(hào) */

#define IDM_START 101/* “啟動(dòng)”菜單項(xiàng)標(biāo)志 */

#define IDM_EXIT102 /* “退出”菜單項(xiàng)標(biāo)志 */

#define UM_SOCK WM_USER+0x100/* 用戶定義網(wǎng)絡(luò)消息 */

ClientMenu MENU/* 客戶菜單 */

BEGIN

POPUP "&Server"

BEGIN

MENUITEM "&Start...", IDM_START

MENUITEM "S&top", IDM_STOP

END

END

#include/* 必須包含winsock.h頭文件 */

HANDLE hInst;

char server_address[256] = {0}; /* 服務(wù)器地址緩沖區(qū) */

char buffer[1024]; /* 接收發(fā)送緩沖區(qū) */

char FAR * lpBuffer = &buffer[0];

SOCKET s = 0; /* 套接字 */

struct sockaddr_in dst_addr;/* 目標(biāo)地址 */

struct hostent *hostaddr; /* 主機(jī)地址 */

struct hostent hostnm;

int count = 0;/* 發(fā)送接收循環(huán)計(jì)數(shù)器 */

客戶程序的窗口主函數(shù)很簡(jiǎn)單,它在注冊(cè)窗口類、建立窗口后,只是給主窗口函數(shù)發(fā)送一個(gè)用戶消息,然后就進(jìn)入Windows消息處理循環(huán)。

程序2:部分Windows程序源代碼(窗口主函數(shù))

int PASCAL WinMain( HANDLE hInstance,HANDLE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)

{

HWND hWnd;

MSG msg;

lstrcpy((LPSTR) server_address, lpCmdLine); /* 取主機(jī)名字 */

if (!hPrevInstance)

if (!InitApplication(hInstance))

return (FALSE);

hInst = hInstance;

hWnd = CreateWindow("ClientClass","Windows ECHO Client",

WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,

CW_USEDEFAULT,CW_USEDEFAULT,

NULL, NULL, hInstance, NULL);

if (!hWnd)

return (FALSE);

ShowWindow(hWnd, nCmdShow);

UpdateWindow(hWnd);

/* 給主窗口函數(shù)發(fā)送WM_USER消息 */

PostMessage(hWnd,WM_USER,(WPARAM) 0, (LPARAM) 0);

while (GetMessage(&msg, NULL, NULL, NULL)) {

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return (msg.wParam);

}

我們用最簡(jiǎn)單的語句編制一個(gè)UNIX下基于BSD SOCKET的服務(wù)器程序,它在建立連接后,只負(fù)責(zé)將收到的數(shù)據(jù)發(fā)回去,在連接斷開后,服務(wù)器關(guān)閉套接字返回。

四、結(jié)束語

我們可以看出,WINSOCK提供的異步選擇機(jī)制使Socket強(qiáng)大的網(wǎng)絡(luò)編程功能能夠在Windows下得到應(yīng)用。相信隨著INTERNET的推廣,TCP/IP網(wǎng)絡(luò)協(xié)議的廣泛使用,使用WINSOCK編制Windows網(wǎng)絡(luò)實(shí)時(shí)通信軟件將能得到較大的發(fā)展。

參考文獻(xiàn):

[1]孫義等,UNIX環(huán)境下的網(wǎng)絡(luò)程序設(shè)計(jì)[M].北京:希望公司,1991.

[2]梁振軍等,新編TCP/IP協(xié)議與計(jì)算機(jī)網(wǎng)絡(luò)互聯(lián)技術(shù)[M].北京:希望公司,1992.

(作者單位:江西省萍鄉(xiāng)市萍鄉(xiāng)廣播電視大學(xué))

宁武县| 务川| 彭阳县| 南平市| 青神县| 旬邑县| 扎囊县| 运城市| 英德市| 虞城县| 武强县| 息烽县| 铁岭县| 灵山县| 察哈| 镇江市| 平陆县| 永清县| 新昌县| 汝城县| 蓝山县| 天镇县| 景洪市| 中牟县| 睢宁县| 黔西县| 乌兰浩特市| 丹阳市| 阆中市| 湘阴县| 金华市| 昌宁县| 巴林左旗| 锡林郭勒盟| 措美县| 潞城市| 阳谷县| 大方县| 冷水江市| 英德市| 镇赉县|