socket编程实验报告Word文档格式.docx
- 文档编号:16155828
- 上传时间:2022-11-21
- 格式:DOCX
- 页数:19
- 大小:684.12KB
socket编程实验报告Word文档格式.docx
《socket编程实验报告Word文档格式.docx》由会员分享,可在线阅读,更多相关《socket编程实验报告Word文档格式.docx(19页珍藏版)》请在冰豆网上搜索。
本单元实验包括的实验项目主要是UDPSocket编程和TCPSocket编程。
本单元实验的主要目的是希望通过本单元实验,让学员掌握Socket编程方法,同时通过本单元实验让学生掌握如何开发基于TCP/IP协议的网络应用。
●实验目的:
通过本实验使学员了解和掌握编写基于UDP协议的网络应用程序。
●实验内容:
编写基于UDP协议网络聊天程序,要求发送程序和接收程序能够接收键盘输入并彼此之间相互发送数据。
●实验步骤:
1.编写server端程序;
2.编写client端程序;
3.client程序与server程序联调;
4.client程序与server程序相互通信。
通过本实验使学员了解和掌握编写基于TCP协议的网络应用程序。
编写基于TCP协议网络聊天程序,要求发送程序和接收程序能够接收键盘输入并彼此之间相互发送数据。
●实验步骤同UDP实验。
二、程序设计
1基于UDP的Socket编程
1.1实验原理:
基于UDP协议的无连接C/S的工作流程
在server端,server首先启动,调用socket()创建套接字,然后调用bind()绑定server的地址(IP+port),调用recvfrom()等待接收数据。
在client端,先调用socket()创建套接字,调用sendto()向server发送数据。
server接收到client发来数据后,调用sendto()向client发送应答数据,client调用recv接收server发来的应答数据。
数据传输结束,server和client通过调用close()关闭套接字。
原理图如图1。
图1UDP通信原理图
1.2实现方案和实验结果
1.2.1方案1:
Linux上两个进程间的通信
方案1实现方案
Ø
server端:
首先调用socket函数创建一个socket,然后调用bind函数将其与本机地址以及一个本地端口号绑定,用recvfrom函数接收到一个client端的消息后,用printf打印出来,server从标准输入设备中取得一行字符串后,调用sendto函数发送给client端。
最后用close关闭该socket。
client机端:
首先调用socket函数创建一个socket,初始化server地址及端口号(实际上就是本机),从标准输入设备中取得字符串,用sendto传送给server端,然后用recv函数接收server端发来的字符串,用printf打印出来。
源代码见附录。
方案1实验结果
server和client通信截图
图2UDPserver
图3UDPClient
1.2.2方案2:
Windows主机(client)和Linux虚拟机(server)之间的进程通信
方案2实现方案
利用Vmwarestation的Linux虚拟机与Windows本机之间的局域网进行进程间通信,Linux虚拟机作为server,Windows本机作为client。
除了Windows使用winsock函数库之外,实现方案与方案1类似,但要注意client端初始化的server地址虽然与方案1相同,但此时已不再是本机地址,而是局域网中Linux虚拟机的IP地址,相当于模拟了不同机器间的进程通信。
方案2实验结果
图4server
图5client
2基于TCP的Socket编程
2.1实验原理:
基于TCP协议的面向C/S的工作流程
在server端,server首先启动,调用socket()创建套接字;
然后调用bind()绑定server的地址(IP+port);
再调用listen()让server做好侦听准备,并规定好请求队列长度,然后server进入阻塞状态,等待client的连接请求;
最后通过accept()来接收连接请求,并获得client的地址。
当accpet接收到一个client发来的connet请求时,将生成一个新的socket,用于传输数据。
在client端,client在创建套接字并指定client的socket地址,然后就调用connect()和server建立连接。
一旦连接建立成功,client和server之间就可以通过调用recv和send来接收和发送数据。
一旦数据传输结束,server和client通过调用close()来关闭套接字。
原理图如图6。
图6
2.2实现方案
首先调用socket函数创建一个Socket,然后调用bind函数将其与本机地址以及一个本地端口号绑定,然后调用listen在相应的socket上监听client,当accpet接收到一个client发来的connet请求时,将生成一个新的socket,用于传输数据。
Recv()接收到一个client端的消息后,server从标准输入设备中取得一行字符串,调用send()发送给client端。
client端:
首先调用socket函数创建一个Socket,初始化server地址及端口号,然后调用connet请求连接监听server。
通过server端accept函数生成的新socket,调用send函数向server端发送从标准输入设备中取得的字符串,然后用recv接收server端发来的字符串。
最后用close()关闭该数据传输socket和监听socket。
2.3实验结果
图7TCPserver
图8TCPserver
三、讨论与心得
记得助教第一节课讲socket的时候,我听得云里雾里的,只觉得是个很神奇的可以实现进程间通信的类似于接口的东西。
印象深刻的是他举的那个打电话的例子,描述得很直观形象。
老师说让我们做这个实验主要是为了体会TCP/IP的原理,并不要求应用做得多么高端,比如图形界面什么的。
我觉得,我既然是网络工程专业的,就更应该学好计算机网络这门课,更好地了解socket编程。
抱着这种决心,我开始了学习。
于是我先去网上找了有关socket编程的讲解,觉得一篇《一切皆socket》的帖子写得很易懂,对于各个函数的功能有了初步的了解。
操作系统的课程也有一个做shell命令解释器的实验,与socket编程实验基本是先后进行的。
在做了shell,熟悉了“一切皆文件”的linux以及编译、运行的方法之后,感觉跟好理解,更好入手了。
我先对照着《一切皆socket》的帖子看老师给的资料附录一中的示例一、二,也就是TCP。
原来socket()是用来创建一个,然后返回值是这个socket的描述符,很类似与文件描述符。
bind()是用来为这个socket绑定server的IP+port地址,当然绑定之前要先对server的地址进行初始化。
listen()的作用是监听client的请求,第二个参数规定了这个刚刚创建的socket可以接受几个client的服务请求。
一旦accept()了一个client的请求,就获得了这个client的地址,这真是个很神奇的东东啊!
操作系统就会又给它分配了一个socket,也就是accept的返回值,用来传输数据。
也就是说,TCP开了2个socket,一个用来监听子进程,一个用来传输数据。
accept之后就可以自由发挥,开始进行网络I/0了!
我们运行程序时可以看到的功能就是在下面的部分实现的。
再往下的收发函数,read()/write(),recv()/send(),readv()/writev(),recvfrom()/sendto(),recvmsg()/sendmsg()什么的,就是用数据传输的socket了,而非监听的socket了。
关于收发函数,我又上网查了一下资料。
拿recv()/send()举例,其实recv只是把TCP协议传过来的数据copy到我们自己定义的buf里去。
而recv所做的把发送缓冲区里的数据被协议发送到接收缓冲区这个过程对于编程用户来讲是不可见的,而recv只是把接收缓冲区里的数据copy出来而已。
Send与之类似。
从这个层面上讲,socket是一个TCP协议提供的接口服务,用传输层的协议干应用层想干的事。
最后不要忘记用close()关掉创建的两个socket。
此外,我大概理解了TCP的三次握手在函数中的体现,要传三个报文,如图1。
图9TCP的三次握手建立连接
看懂、理解了代码后,我把代码拷了进去,调试成功后,看到了server会把client发过来的数据再返回去,我觉得这个没什么意义,就想改编它,让server也可以通过输入回答client。
于是就又定义了一个buf3,用gets函数接受标准输入到buf3里,然后用把buf3的内容发给client。
一个偶然的发现让我理解了TCP所谓的四次握手释放过程。
当我把client关掉时,server就自动关掉了。
当client首先调用close主动关闭连接,这时TCP发送一个FINM;
另一端接收到FINM之后,执行被动关闭,对这个FIN进行确认。
它的接收也作为文件结束符传递给server的应用程序,因为FIN的接收意味着server的应用进程在相应的连接上再也接收不到额外数据;
一段时间之后,server上接收到文件结束符的应用进程调用close关闭它的socket。
这导致它的TCP也发送一个FINN;
接收到这个FIN的源发送端TCP对它进行确认。
这样每个方向上都有一个FIN和ACK。
图10socket中发送的TCP四次握手释放
调通了TCP之后,我去尝试UDP。
其实这顺序是反了的,因为UDP貌似更简单一些,可是因为TCP有现成的代码,所以就先理解了TCP。
之后去查UDP的资料,直观上感觉除了创建socket()时定义的协议不同外,就是少了一些函数,少用了一个socket。
对于server来讲,bind()之后,不用再listen和accept了,就是不用监听了,直接用这个socket来进行数据传输就可以了。
于是我就想当然地觉得下面进行网络I/O的收发函数应该是差不多的,就直接用了刚才在TCP里用的recv和send。
对于client来讲,我也是直接用的这两个函数。
然后怎么都传不了数据,实现不了通信。
于是我仔细比较了几个函数的参数,发现recvfrom比recv多了2个参数,后来理解了一下,这是因为TCP在accept时就为与之通信的每个进程分配了一个socket用于数据传输,也就是说对于server的每个client都有一个专门的进程与其进行通信。
而UDP没有开另外的进程,也就是没有创建新的socket,所以server的多个client是共用这一个socket的,可以说是多路复用了。
为了辨别多个client,server需要client的地址(ip+port)来接受和发送,于是就要用recvfrom多出来的2个参数,即client的地址和地址长度。
这也就同时解释了为什么UDP只创建一个socket就够了。
对于UDP的client端来说,只需要在发送数据的时候用sendto来表明server的地址,在接收数据时就不需要的了,因为只有一个server,不需要标记了。
因为我是在虚拟机上进行的以上实验,我就想利用主机和虚拟机之间的局域网来建立连接,进行进程通信。
虽然操作系统
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- socket 编程 实验 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)