基于WSAAsyncSelect模型的通信程序设计.doc
- 文档编号:1221256
- 上传时间:2023-04-30
- 格式:DOC
- 页数:8
- 大小:88KB
基于WSAAsyncSelect模型的通信程序设计.doc
《基于WSAAsyncSelect模型的通信程序设计.doc》由会员分享,可在线阅读,更多相关《基于WSAAsyncSelect模型的通信程序设计.doc(8页珍藏版)》请在冰点文库上搜索。
集美大学计算机工程学院实验报告
课程名称:
TCP/IP协议与通信程序设计
班级:
实验成绩:
实验项目名称:
基于WSAAsyncSelect模型的通信程序设计
学号:
上机实践日期:
2016-05-12
实验项目编号:
08
组号:
1
上机实践时间:
2学时
一、实验目的
了解基于WSAAsyncSelect模型通信程序的编写,编译和执行
二、实验内容与设计思想
编写Win32程序模拟实现基于WSAAsyncSelect模型的两台计算机之间的通信,要求编程实现服务器端与客户端之间双向数据传递。
客户端向服务器端发送“请输出从1到1000内所有的质数”,服务器回应客户端给出结果。
三、实验使用环境
操作系统:
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();
}
};
CInitSocktheSock;//加载套接字库
LRESULTCALLBACKWindowProc(HWNDhWnd,UINTuMsg,WPARAMwParam,LPARAMlParam);
boolisprime(intp){//判断p是否为质数
intsq=(int)sqrt(p);
boolflag=true;
inti;
for(i=2;i<=sq;i++){
if(p%i==0){
flag=false;
break;
}
}
if(!
flag&&i<=sq)
returnfalse;
else
returntrue;
};
char*getallprime(intn){//将num以内的所有质数放在同一字符串中
charszprime[4096]="质数:
";
intlen=strlen(szprime)+strlen(",");
for(inti=2;i<=n;i++){
if(isprime(i)){
charsznum[10];
itoa(i,sznum,10);
char*sztemp=strcat(szprime,sznum);
len+=strlen(sznum);
szprime[len-1]=',';
len+=strlen(",");
}
}
//printf("%s\n",szprime);
returnszprime;
};
intmain()
{
charszClassName[]="MainWClass";
WNDCLASSEXwndclass;
//用描述主窗口的参数填充WNDCLASSEX结构
wndclass.cbSize=sizeof(wndclass);
wndclass.style=CS_HREDRAW|CS_VREDRAW;
wndclass.lpfnWndProc=WindowProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hInstance=NULL;
wndclass.hIcon=:
:
LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor=:
:
LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground=(HBRUSH):
:
GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=szClassName;
wndclass.hIconSm=NULL;
:
:
RegisterClassEx(&wndclass);
//创建主窗口
HWNDhWnd=:
:
CreateWindowEx(
0,
szClassName,
"",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
NULL,
NULL);
if(hWnd==NULL)
{
:
:
MessageBox(NULL,"创建窗口出错!
","error",MB_OK);
return-1;
}
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;
}
//将套接字设为窗口通知消息类型。
:
:
WSAAsyncSelect(sListen,hWnd,WM_SOCKET,FD_ACCEPT|FD_CLOSE);
//进入监听模式
:
:
listen(sListen,5);
//从消息队列中取出消息
MSGmsg;
while(:
:
GetMessage(&msg,NULL,0,0))
{
//转化键盘消息
:
:
TranslateMessage(&msg);
//将消息发送到相应的窗口函数
:
:
DispatchMessage(&msg);
}
//当GetMessage返回0时程序结束
returnmsg.wParam;
}
LRESULTCALLBACKWindowProc(HWNDhWnd,UINTuMsg,WPARAMwParam,LPARAMlParam)
{
switch(uMsg)
{
caseWM_SOCKET:
{
//取得有事件发生的套节字句柄
SOCKETs=wParam;
//查看是否出错
if(WSAGETSELECTERROR(lParam))
{
:
:
closesocket(s);
return0;
}
//处理发生的事件
switch(WSAGETSELECTEVENT(lParam))
{
caseFD_ACCEPT:
//监听中的套接字检测到有连接进入
{
SOCKETclient=:
:
accept(s,NULL,NULL);
:
:
WSAAsyncSelect(client,hWnd,WM_SOCKET,FD_READ|FD_WRITE|FD_CLOSE);
}
break;
caseFD_WRITE:
{
}
break;
caseFD_READ:
{
charszText[1024]={0};
if(:
:
recv(s,szText,1024,0)==-1)
:
:
closesocket(s);
else
{
printf("接收数据:
%s",szText);
char*szReply=getallprime(1000);//得到1000以内的所有质数
:
:
send(s,szReply,strlen(szReply),0);//响应客户端,回以szReply
}
}
break;
caseFD_CLOSE:
{
:
:
closesocket(s);
}
break;
}
}
return0;
caseWM_DESTROY:
:
:
PostQuitMessage(0);
return0;
}
//将我们不处理的消息交给系统做默认处理
return:
:
DefWindowProc(hWnd,uMsg,wParam,lParam);
}
客户端:
#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("127.0.0.1");//没有联网,直接使用127.0.0.1即可
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.执行结果并非为质数,且出现重复
经过调试分析服务器端质数放在同一字符串的函数中,发现未将分隔符号“,”的长度加进去导致整个质数的输出结果出现混乱
2.客户端接收数据时发现349之后的质数未显示
查看判断是否为质数及所有质数放在同一字符串中的函数时发现并没有将之后的数据隔离,反复检查发现是客户端定义接收数据的长度时由于直接利用上次实验,未将长度增大,仅为256导致后面的数据未被接收
六、附录
《网络编程技术与应用》
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 WSAAsyncSelect 模型 通信 程序设计