//////////////////////////////////////////////////
// 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);