天天看點

WSAEventSelect事件Select模型Client——》Server

//////////////////////////////////////////////////

// WSAEventSelect檔案

#include <winsock2.h>

#pragma comment(lib, "WS2_32")

class CInitSock

{

public:

CInitSock();

~CInitSock();

};

inline CInitSock::CInitSock()

// 初始化WS2_32.dll

WSADATA wsaData;

WORD sockVersion = MAKEWORD(2, 2);

if(::WSAStartup(sockVersion, &wsaData) != 0)

exit(0);

}

inline CInitSock::~CInitSock()

::WSACleanup();

#include <stdio.h>

#include <iostream.h>

#include <windows.h>

// 初始化Winsock庫

CInitSock theSock;

int main1();

int main2();

void main()

printf("Please select a item:/n");

printf("s:Server/n");

printf("c:Client/n");

char a;

while(1){

scanf("%c",&a);

if(a=='s'){main1();break;}

else if(a=='c'){main2();break;}

else continue;

int main1()

// 事件句柄和套節字句柄表

WSAEVENT eventArray[WSA_MAXIMUM_WAIT_EVENTS];

SOCKET sockArray[WSA_MAXIMUM_WAIT_EVENTS];

int nEventTotal = 0;

USHORT nPort = 4567; // 此伺服器監聽的端口号

// 建立監聽套節字

SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

sockaddr_in sin;

sin.sin_family = AF_INET;

sin.sin_port = htons(nPort);

sin.sin_addr.S_un.S_addr = INADDR_ANY;

if(::bind(sListen, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR)

printf(" Failed bind() /n");

return -1;

::listen(sListen, 5);

// 建立事件對象,并關聯到新的套節字

WSAEVENT event = ::WSACreateEvent();

::WSAEventSelect(sListen, event, FD_ACCEPT|FD_CLOSE);

// 添加到表中

eventArray[nEventTotal] = event;

sockArray[nEventTotal] = sListen;

nEventTotal++;

// 處理網絡事件

while(TRUE)

// 在所有事件對象上等待

int nIndex = ::WSAWaitForMultipleEvents(nEventTotal, eventArray, FALSE, WSA_INFINITE, FALSE);

// 對每個事件調用WSAWaitForMultipleEvents函數,以便确定它的狀态

nIndex = nIndex - WSA_WAIT_EVENT_0;

for(int i=nIndex; i<nEventTotal; i++)

nIndex = ::WSAWaitForMultipleEvents(1, &eventArray[i], TRUE, 1000, FALSE);

if(nIndex == WSA_WAIT_FAILED || nIndex == WSA_WAIT_TIMEOUT)

continue;

else

// 擷取到來的通知消息,WSAEnumNetworkEvents函數會自動重置受信事件

WSANETWORKEVENTS event;

::WSAEnumNetworkEvents(sockArray[i], eventArray[i], &event);

if(event.lNetworkEvents & FD_ACCEPT) // 處理FD_ACCEPT通知消息

if(event.iErrorCode[FD_ACCEPT_BIT] == 0)

if(nEventTotal > WSA_MAXIMUM_WAIT_EVENTS)

printf(" Too many connections! /n");

SOCKET sNew = ::accept(sockArray[i], NULL, NULL);

::WSAEventSelect(sNew, event, FD_READ|FD_CLOSE|FD_WRITE);

sockArray[nEventTotal] = sNew;

else if(event.lNetworkEvents & FD_READ) // 處理FD_READ通知消息

if(event.iErrorCode[FD_READ_BIT] == 0)

char szText[256];

char temp;

int nRecv = ::recv(sockArray[i], szText, strlen(szText), 0);

if(nRecv > 0)

temp=szText[nRecv];

szText[nRecv] = '/0';

printf("接收到資料:%s /n", szText);

szText[nRecv]=temp;

else if(event.lNetworkEvents & FD_CLOSE) // 處理FD_CLOSE通知消息

if(event.iErrorCode[FD_CLOSE_BIT] == 0)

::closesocket(sockArray[i]);

for(int j=i; j<nEventTotal-1; j++)

sockArray[j] = sockArray[j+1];

nEventTotal--;

else if(event.lNetworkEvents & FD_WRITE) // 處理FD_WRITE通知消息

return 0;

//Client

int main2()

// 建立套節字

SOCKET s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if(s == INVALID_SOCKET)

printf(" Failed socket() /n");

// 也可以在這裡調用bind函數綁定一個本地位址

// 否則系統将會自動安排

// 填寫遠端位址資訊

sockaddr_in servAddr;

servAddr.sin_family = AF_INET;

servAddr.sin_port = htons(4567);

// 注意,這裡要填寫伺服器程式(TCPServer程式)所在機器的IP位址

// 如果你的計算機沒有聯網,直接使用127.0.0.1即可

servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

if(::connect(s, (sockaddr*)&servAddr, sizeof(servAddr)) == -1)

printf(" Failed connect() /n");

while(TRUE){

scanf("%s",szText);

//puts(szText);

// 向伺服器端發送資料

::send(s, szText, strlen(szText), 0);

// 關閉套節字

::closesocket(s);

繼續閱讀