实验二实验报告

上传人:ji****72 文档编号:31504245 上传时间:2018-02-08 格式:DOC 页数:8 大小:309KB
返回 下载 相关 举报
实验二实验报告_第1页
第1页 / 共8页
实验二实验报告_第2页
第2页 / 共8页
实验二实验报告_第3页
第3页 / 共8页
实验二实验报告_第4页
第4页 / 共8页
实验二实验报告_第5页
第5页 / 共8页
点击查看更多>>
资源描述

《实验二实验报告》由会员分享,可在线阅读,更多相关《实验二实验报告(8页珍藏版)》请在金锄头文库上搜索。

1、网络程序设计实验报告实验名称:_ _UDP 通信实验 _实验类型: _ _验证型实验 指导教师: _ _ _专业班级:_ _ _ _姓 名:_ _ _学 号: _ 电子邮件:_ _ 实验地点:_ 实验成绩:_ 一、实验目的 1、进一步理解 Winsock API 的调用方法 2、了解 UDP 协议的工作原理 3、掌握 UDP 服务端程序和客户端程序的编写流程 4、熟悉程序的调试方法。二、实验设计1、数据报套接字编程模型时序和流程图 1:流套接字编程时序图2、用到的 Winsock API 函数有:1)、创建套接字函数 socket()SOCKET socket(int af,int type,

2、int protocol) ;由于采用数据报套接字进行数据传输,因此 type 参数必须设置为SOCK_DGRAM,protocol 参数必须设置为 IPPROTO_UDP2)、绑定本地地址到所创建的套接字函数 bind()int bind(SOCKET s,const struct sockaddr* name,int namelen) ;3)、接收数据函数 recvfrom()服务应答服务请求阻塞,等待客户连接请求服务端socket()bind()recvfrom()bind()处理服务请求sendto()closesocket()recvfrom()closesocket()sendto

3、()客户端socket()int recvfrom(SOCKET s,char* buf ,int len,int flags,struct sockaddr* from,int* fromlen) ;4)、发送数据函数 sendto()int sendto(SOCKET s,const char* buf ,int len,int flags,const struct sockaddr* to,int* tolen) ;5)、关闭套接字函数 closesocket()int closesocket( SOCKET s) ;3、服务端的程序流程图如下:说明:服务端的程序首先要调用函数socke

4、t(AF_INET,SOCK_DGRAM,IPPROTO_UDP)创建一个监听套接字,用于监听是否有客户端发送数据过来,然后调用 bind(s,(LPSOCKADDR)&sin,sizeof(sin) 绑定该监听套接字到一个本地地址,接下来是一个循环语句,循环跳出的条件是客户端发来的数据是bye或自己发送给客户端的数据为bye ,当接收到数据为bye或自己发出bye时关闭套接字,结束程序,否则就接受数据,输出接受到的数据,然后输入发送给客户端的数据,以此循环。开 始调 用 函 数 :s o c k e t ( A F _ I N E T , S O C K _ D G R A M , I PP

5、 R O T O _ U D P )创 建 监 听 套 接 字调 用 函 数 :b i n d ( s , ( L P S O C K A D D R ) & s i n , s i z e o f ( s i n ) )绑 定 监 听 套 接 字 到 一 个 本 地 地 址调 用 r e c v f r o m 接 受 客 户 端发 来 的 数 据 , 将 受 到 的 数据 存 放 在 r e c M s g 字 符 串 中r e c M s g 是 否 为 b y e ?YN调 用 c l o s e s o c k e t ( s )关 闭 套 接 字结 束输 入 发 送 给 客 户 端

6、的 数 据 s e n d M s g ,并 调 用 s e n d t o 函 数发 送 数 据 给 客 户 端s e n d M s g 是 否 为 b y e ?YN输 出 接 收到 的 数 据Y图 2:服务端收发数据的流程图4、客户端的程序流程图如下:说明:客户端的程序首先要调用函数 socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)创建一个套接字,然后声明一个 sockaddr_in 类型的变量 addr,存放服务端的地址信息,接下来是一个循环语句,循环跳出的条件是服务端发来的数据是bye或自己发送给服务端的数据为bye ,当接收到数据为bye或自己发出by

7、e时关闭套接字,结束程序,否则就输入发送给服务端的数据,接受数据,输出收到的数据,以此循环。开 始调 用 函 数 : s o c k e t ( A F _ I N E T , S O C K _ D G R A M , I P P R O T O _ U D P ) 创建 一 个 套 接 字将 服 务 端 的 地 址 信 息 保 存 在 类型 为 s o c k a d d r _ i n 的 a d d r 里 面输 入 发 送 给 服 务 端 的 数 据s e n d M s g , 并 调 用 s e n d t o函 数 发 送 数 据 给 服 务 端s e n d M s g 是

8、否 为 b y e ?YN调 用 c l o s e s o c k e t ( s )关 闭 套 接 字结 束调 用 r e c v f r o m 接 受服 务 端 发 来 的 数据 , 将 受 到 的 数据 存 放 在 r e c M s g字 符 串 中s e n d M s g 是 否 为 b y e ?YN输 出 接 收到 的 数 据图 2:客户端收发数据的流程图三、实验过程(包含实验结果)1、遇到的错误有:1) 、当客户端发送bye时,服务端收到数据,但是客户端和服务端都未结束通话错误原因:当判断接受数据是否为bye时,用的代码是 if (recMsg=”bye”),未用判断字符

9、串的函数 strcmp(recMsg,bye),当客户端发送bye后,未判断自己是否发送的bye导致客户端未退出。2、实验结果:1) 、服务端运行结果如下:2) 、客户端运行结果如下:四、讨论与分析1) 、能否在接收数据之间不进行 bind()调用?如果能,请说明可能的情况。答:创建套接字之后,如果首先调用的是 sendto 函数,则可以不调用 bind 函数显式地绑定本地地址,系统会自动为程序绑定,但是如果创建套接字后,直接调用 recvfrom 就会失败,因为套接字还没有绑定。 2) 、能否使用 connect()连接对方?为什么?答:UDP 中可以使用 connect 系统调用,UDP

10、中 connect 操作与 TCP 中 connect 操作有着本质区别,TCP 中调用 connect 会引起三次握手,client 与 server 建立连结,UDP 中调用connect 内核仅仅把对端 ip 和 port 记录下来,UDP 中可以多次调用 connect,TCP 只能调用一次 connect。采用 connect 的 UDP 发送接受报文可以调用 send,write 和 recv,read 操作.当然也可以调用 sendto,recvfrom.调用 sendto 的时候第五个参数必须是 NULL,第六个参数是 0.调用 recvfrom,recv,read 系统调用只

11、能获取到先前 connect 的 ip&port 发送的报文。3) 、能否在不调用 sendto()函数之前调用 recvfom()函数。答:服务端可以在不调用 sendto()函数之前调用 recvfom()函数,因为服务端要在接受到客户端数据后才发送数据到客户端,但是客户端必须先调用 sendto 函数后才能调用recvfom 函数,因为,当没有客户端发来数据时,服务端一直处于监听状态,客户要先调用 sendto 函数才能让服务端不处于阻塞模式,然后再调用 recvfom 接受服务端发来的数据。五、实验者自评由于本次实验是验证型实验,代码是书上现成的,但是通过自己看代码,分析代码并画出了程

12、序的流程图,我进一步理解了 Winsock API 的调用方法,也了解了 UDP 协议的工作原理,并掌握了 UDP 服务端程序和客户端程序的编写流程,在做实验的过程中也出现了许多问题,通过调试代码,我更加熟悉了程序的调试方法,把遇到的问题都一一解决了,而且通过实际分析代码,修改代码,对老师课堂上将的理论知识理解更加深刻,体会也更加深刻。通过此次的实验,我达到了本次实验的目的,也巩固了课堂上老师讲授的基础知识,是一次非常有意义的实验。六、附录:关键代码(给出适当注释,可读性高)1、服务端程序代码:#include #include initsock.hCInitSock initSock;/初始

13、化 Winsock 库int main()/创建套接字SOCKET s=:socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);if(s = INVALID_SOCKET)printf(Failed socket()n);return 0;/填充 sockaddr_in 结构sockaddr_in sin;sin.sin_family=AF_INET;sin.sin_port=htons(4567);sin.sin_addr.S_un.S_addr=INADDR_ANY;/绑定这个套接字到一个本地地址if (:bind(s,(LPSOCKADDR)&sin,sizeof

14、(sin)=SOCKET_ERROR)printf(Faild bind()n);return 0;printf(nnn *服务端*nn);char recMsg1024;char sendMsg1024;sockaddr_in addr;int nLen=sizeof(addr);printf(等待数据的到来:n);while(TRUE)int nRecv=:recvfrom(s,recMsg,1024,0,(sockaddr*)if (nRecv0)recMsgnRecv=0;printf(接收到数据(%s):%sn,:inet_ntoa(addr.sin_addr), recMsg);i

15、f (strcmp(recMsg,bye)=0)printf(关闭套接字,结束对话!);:closesocket(s);return 0;printf(请输入发送数据:n);gets(sendMsg);:sendto(s, sendMsg, strlen(sendMsg), 0, (sockaddr*)if (strcmp(sendMsg,bye)=0)printf(关闭套接字,结束对话!);:closesocket(s);return 0;:closesocket(s);2、客户端程序代码:#include #include initsock.hCInitSock initSock;/初始化 Winsock 库int main() SOCKET s = :socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);if(s = INVALID_SOCKET)printf(Failed socket() %d n

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号