基于WSAEventSelect模型的通信程序设计.docx
《基于WSAEventSelect模型的通信程序设计.docx》由会员分享,可在线阅读,更多相关《基于WSAEventSelect模型的通信程序设计.docx(11页珍藏版)》请在冰点文库上搜索。
基于WSAEventSelect模型的通信程序设计
集美大学计算机工程学院实验报告
课程名称:
TCP/IP协议与通信程序设计
班级:
网络
实验成绩:
实验项目名称:
基于WSAEventSelect模型的通信程序设计
学号:
上机实践日期:
2016-05-19
实验项目编号:
09
组号:
1
上机实践时间:
2学时
一、实验目的
了解基于WSAEventSelect模型通信程序的编写,编译和执行
二、实验内容与设计思想
编写Win32程序模拟实现基于WSAEventSelect模型的两台计算机之间的通信,要求编程实现服务器端与客户端之间双向数据传递。
客户端向服务器端发送“请输出从1到1000内所有的水仙花数”,服务器回应客户端给出结果。
(水仙花数是一个三位数,它等于各位数字的立方和,例如153)
三、实验使用环境
操作系统:
MicrosoftWindowsXPSP2
编程环境:
VisualC++6.0
四、实验步骤和调试过程
源代码:
服务器:
#include
#include
#pragmacomment(lib,"WS2_32")//链接到WS2_32.lib
#include
#defineWM_SOCKETWM_USER+101//自定义消息
classCInitSock
{
public:
CInitSock(BYTEminorVer=2,BYTEmajorVer=2)
{
//初始化WS2_32.dll
WSADATAwsaData;
WORDsockVersion=MAKEWORD(minorVer,majorVer);
if(:
:
WSAStartup(sockVersion,&wsaData)!
=0)
return;
}
~CInitSock()
{
:
:
WSACleanup();
}
};
//初始化Winsock库
CInitSocktheSock;
boolisnarcissus(intn){//判断n是否为水仙花数
inti,j,k;
//将3位数的个,十,百位分别提取出来
i=n/100;
j=(n%100)/10;
k=(n%100)%10;
if((i*100+j*10+k)==((i*i*i)+(j*j*j)+(k*k*k)))
returntrue;
returnfalse;
};
char*getallnarcissus(intn){//将n以内的所有水仙花数放在同一字符串中
charsznarcissus[4096]="水仙化数:
";
intlen=strlen(sznarcissus)+strlen(",");
if(n>=1000)//因为水仙花数是一个三位数,若大于三位数将其置为999
n=999;
for(inti=100;i<=n;i++){
if(isnarcissus(i)){
charsznum[5];
itoa(i,sznum,10);//因为接收发送数据只处理字符串数组类型,使用itoa转换int型为字符数组类型
char*sztemp=strcat(sznarcissus,sznum);//将每次判断的水仙花数添加到字符串数组中
len+=strlen(sznum);
sznarcissus[len-1]=',';
len+=strlen(",");
}
}
returnsznarcissus;
};
intmain()
{
//事件句柄和套节字句柄表
WSAEVENTeventArray[WSA_MAXIMUM_WAIT_EVENTS];
SOCKETsockArray[WSA_MAXIMUM_WAIT_EVENTS];
intnEventTotal=0;
USHORTnPort=4567;//此服务器监听的端口号
//创建监听套节字
SOCKETsListen=:
:
socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
sockaddr_insin;
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("Failedbind()\n");
return-1;
}
:
:
listen(sListen,5);
//创建事件对象,并关联到新的套节字
WSAEVENTevent=:
:
WSACreateEvent();
:
:
WSAEventSelect(sListen,event,FD_ACCEPT|FD_CLOSE);
//添加到表中
eventArray[nEventTotal]=event;
sockArray[nEventTotal]=sListen;
nEventTotal++;
//处理网络事件
while(TRUE)
{
//在所有事件对象上等待
intnIndex=:
:
WSAWaitForMultipleEvents(nEventTotal,eventArray,FALSE,WSA_INFINITE,FALSE);
//对每个事件调用WSAWaitForMultipleEvents函数,以便确定它的状态
nIndex=nIndex-WSA_WAIT_EVENT_0;
for(inti=nIndex;i{
nIndex=:
:
WSAWaitForMultipleEvents(1,&eventArray[i],TRUE,1000,FALSE);
if(nIndex==WSA_WAIT_FAILED||nIndex==WSA_WAIT_TIMEOUT)
{
continue;
}
else
{
//获取到来的通知消息,WSAEnumNetworkEvents函数会自动重置受信事件
WSANETWORKEVENTSevent;
:
:
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("Toomanyconnections!
\n");
continue;
}
SOCKETsNew=:
:
accept(sockArray[i],NULL,NULL);
WSAEVENTevent=:
:
WSACreateEvent();
:
:
WSAEventSelect(sNew,event,FD_READ|FD_CLOSE|FD_WRITE);
//添加到表中
eventArray[nEventTotal]=event;
sockArray[nEventTotal]=sNew;
nEventTotal++;
}
}
elseif(event.lNetworkEvents&FD_READ)//处理FD_READ通知消息
{
if(event.iErrorCode[FD_READ_BIT]==0)
{
charszText[256];
intnRecv=:
:
recv(sockArray[i],szText,strlen(szText),0);//接收客户端发送的数据
if(nRecv>0)
{
szText[nRecv]='\0';
printf("接收到数据:
%s\n",szText);
char*szReply=getallnarcissus(1000);//得到1到1000内所有的水仙花数
:
:
send(sockArray[i],szReply,strlen(szReply),0);//发送数据到客户端
}
}
}
elseif(event.lNetworkEvents&FD_CLOSE)//处理FD_CLOSE通知消息
{
if(event.iErrorCode[FD_CLOSE_BIT]==0)
{
:
:
closesocket(sockArray[i]);
for(intj=i;j{
sockArray[j]=sockArray[j+1];
sockArray[j]=sockArray[j+1];
}
nEventTotal--;
}
}
elseif(event.lNetworkEvents&FD_WRITE)//处理FD_WRITE通知消息
{
}
}
}
}
return0;
}
客户端:
#include
#include
#pragmacomment(lib,"WS2_32")//链接到WS2_32.lib
classCInitSock
{
public:
CInitSock(BYTEminorVer=2,BYTEmajorVer=2)
{
//初始化WS2_32.dll
WSADATAwsaData;
WORDsockVersion=MAKEWORD(minorVer,majorVer);
if(:
:
WSAStartup(sockVersion,&wsaData)!
=0)
return;
}
~CInitSock()
{
:
:
WSACleanup();
}
};
CInitSocktheSock;//加载套接字库
intmain()
{
//创建套节字
SOCKETs=:
:
socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(s==INVALID_SOCKET)
{
printf("Failedsocket()\n");
return0;
}
//也可以在这里调用bind函数绑定一个本地地址,无则系统将会自动安排
//填写远程地址信息
sockaddr_inservAddr;
servAddr.sin_family=AF_INET;
servAddr.sin_port=htons(4567);
//要连接的服务器地址
servAddr.sin_addr.S_un.S_addr=inet_addr("219.228.247.127");
if(:
:
connect(s,(sockaddr*)&servAddr,sizeof(servAddr))==-1)
{
printf("Failedconnect()\n");
return0;
}
//发送数据
charbuf[]="请输出从1到1000内所有的水仙花数";
printf("发送数据:
%s\n",buf);
send(s,buf,strlen(buf),0);
Sleep(6);
//接收数据
charbuff[3000];
intnRecv=:
:
recv(s,buff,3000,0);
if(nRecv>0)
{
buff[nRecv]='\0';
printf("接收到数据:
\n%s\n",buff);
}
//关闭套节字
:
:
closesocket(s);
return0;
}
执行结果:
五、实验小结
1.执行结果出现将1-1000所有的数均发送即判断为水仙花数
经查看判断水仙花数的函数isnarcissus(intn),发现在判断该数等于各位数字的立方和的if语句中,仅仅将为真的情况执行返回ture,漏掉将其它情况返回false。
2.水仙花数特指3位数,所以当所要求的范围不在100-999之间时应将判断的范围调整为100-999,即进行for循环判断时以100开始,且用if(n>=1000)n=999;语句进行相应的范围判断从而调整上界n的值
六、附录
《网络编程技术与应用》
(注:
文档可能无法思考全面,请浏览后下载,供参考。
可复制、编制,期待你的好评与关注)