1)选择模型(SelectModel)本次实验使用了事件选择模型,所以下面介绍事件选择模型:
2)异步选择模型(WSAAsyncSelectModel)
3)事件选择模型(WSAEventSelectModel)
4)重叠模型(OverlappedModel)
5)完成端口模型(CompletionPortModel
(1).创建一个事件句柄表和一个对应的套接字句柄表。2、实验设计
(2).每创建一个套接字,就创建一个事件对象,把它们的句柄分别放入上面的两个表中,并调用WSAEventSelect将二者关联起来。
(3).调用WSAWaitForMultipleEvents在所有事件对象上等待(bWaitAll=FALSE),函数返回后,从第一个有信号的事件对象开始检查事件对象表中的事件对象是否有信号(再次调用WSAWaitForMultipleEvents)。
(4).调用WSAEnumNetworkEvents(),获取套接字上相应的网络事件并处理,然后继续在事件对象上等待。
(二)实验过程
运行服务器和客户端,建立连接之后,服务器会显示客户端的信息。
客户端与服务器之间能进行通信而且能互相发消息。
服务器能选择客户端进行发消息。
当某一客户端输入“bye”之后,关闭连接。
int WSAEventSelect(
__in SOCKET s, //代表感兴趣的套接字
__in WSAEVENT hEventObject, //指定要与套接字关联在一起的事件对象,即用 WSACreateEvent 创建的那一个
__in long lNetworkEvents //对应一个“位掩码”,用于指定应用程序感兴趣的各种网络事件类型的一个组合。
);
其中参数 lNetworkEvents可以用以下数值进行OR操作, FD_READ 应用程序想要接收有关是否可读的通知,以便读入数据, FD_WRITE 应用程序想要接收有关是否可写的通知,以便写入数据,FD_ACCEPT 应用程序想接收与进入连接有关的通知, FD_CONNECT 应用程序想接收与一次连接完成的通知, FD_CLOSE 应用程序想接收与套接字关闭的通知
2. 简述你所使用的I/O模型的编程步骤。
(1).创建一个事件句柄表和一个对应的套接字句柄表。
(2).每创建一个套接字,就创建一个事件对象,把它们的句柄分别放入上面的两个表中,并调用WSAEventSelect将二者关联起来。
(3).调用WSAWaitForMultipleEvents在所有事件对象上等待(bWaitAll=FALSE),函数返回后,从第一个有信号的事件对象开始检查事件对象表中的事件对象是否有信号(再次调用WSAWaitForMultipleEvents)。
(4).调用WSAEnumNetworkEvents(),获取套接字上相应的网络事件并处理,然后继续在事件对象上等待。
3. 在你所使用的I/O中如何判断发生网络事件或者IO完成的套接字?
答:WSAWaitForMultipeEvent判断,WSAWaitForMultipeEvent函数会等待网络事件的发生。
1、服务器端:
int _tmain(int argc, _TCHAR* argv[])
{
unsigned short dWsa = MAKEWORD(2, 2);
WSADATA lpwsadata;
if (0 != WSAStartup(dWsa, &lpwsadata))
cout << "error";
else cout << "-------------------服务器已启动----------------------" << endl;
SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sListen == INVALID_SOCKET)
{
cout << "FAILED SOCKET()";
return 0;
}
sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(5555);
saddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (bind(sListen, (LPSOCKADDR)&saddr, sizeof(saddr)) == SOCKET_ERROR)
{
cout << "failed bind()";
return 0;
}
listen(sListen, 5);
//数组保存;
int totalevent=0;
SOCKET SOCKETARRAY[WSA_MAXIMUM_WAIT_EVENTS]; //socket数组,WSAWaitForMultipleEvents 只能支持由 WSA_MAXIMUM_WAIT_EVENTS 对象规定的一个最大值,在此定义成64个
WSAEVENT EVENTARRAY[WSA_MAXIMUM_WAIT_EVENTS]; //事件数组
WSAEVENT event=WSACreateEvent();
WSAEventSelect(sListen,event,FD_ACCEPT|FD_CLOSE);
EVENTARRAY[totalevent]=event;
SOCKETARRAY[totalevent]=sListen;
totalevent++;
while(1)
{
int index=WSAWaitForMultipleEvents(totalevent,EVENTARRAY,FALSE,WSA_INFINITE,NULL);
index=index-WSA_WAIT_EVENT_0;
cout<<"发生事件对象索引:"<0)
{
buffer[ret]='\0';
cout<<"收到消息: "<> sSend;
cout <<"请输入要发送的信息" << endl;
cin>>buffer;
SOCKETARRAY[i] = sSend;
send(SOCKETARRAY[i],buffer,strlen(buffer),0); //
send(SOCKETARRAY[i],buffer,ret,0);
system("color 0F");
if (WSAGetLastError()==0)
cout<<"消息成功发送!"<
2、客户端:
int _tmain(int argc, _TCHAR* argv[])
{
unsigned short dWsa = MAKEWORD(2, 2);//无符号短整型 宏创建一个被指定变量连接而成的WORD变量。返回一个WORD变量。
WSADATA lpwsadata;//用来存储 被WSAStartup函数调用后返回的 Windows Sockets 数据
if( 0 != WSAStartup(dWsa,&lpwsadata))
cout<<"error";
else cout<<"-------------------客户端已启动----------------------"<>buf;
if(!strcmp(buf,"bye"))
{
closesocket(sClient);
return 0;
}
send(sClient,buf,strlen(buf),0);
//system("color 0F");
int num=recv(sClient,buf,1024,0);
if(num>0)
{
buf[num]='\0';
cout<